一、多线程
1.认识多线程
①线程
②多线程
2.创建线程方式
①方式一:继承Thread类
1.让子类继承Thread线程类
2.重写run方法,就是这个线程执行会执行的操作。
3.创建继承Thread的子类对象就代表一个线程
4.启动线程:.start()-自动执行run方法
注意:main是一条默认的主线程,这个子类对象是子线程
对于第一条,相当于把子线程就当一个对象执行它的方法
对于第二条,如果放在前面,执行不到start方法就启动不了子线程
②方式二:实现Runnable接口
1.定义一个任务类,实现Runnable接口
2.重写Runnable的run方法
3.创建任务对象
4.把任务对象交给一个线程对象
其匿名内部类写法:
③方式二:利用Callable接口、FutureTask类
前面两个方式都不能返回值run方式是void
实现Callable,要执行的操作
Callable是泛型接口,要返回什么类型数据就在<>填
3.Thread线程类的常用方法
注意:currentThread方法是在哪个线程里执行就会拿到哪个线程对象
所以拿到名字可以判断是哪个线程在执行操作
设置名字:在使用构造器创建线程对象设置名字就需要在创建的那个线程类构造器使用Thread的构造器
sleep、join方法:
如果这样就会让t1,t2,t3线程顺序执行完毕
4.线程安全
模拟线程安全问题
第二个判断的时候,第一个取钱的操作还没执行,就还可以取钱,出现线程安全
5.线程同步
①认识线程同步:
②方式一:同步代码块
双引号代表的对象只有一份,就限制了所有线程访问此核心判断代码都只能一个接着一个进行,这样如果是另一个账户对象要取钱就不能操作了
普通成员方法建议使用this
静态方法,调用时使用类名,所以建议使用类名作为锁
③方式二:同步方法
就是在方法前加修饰词synchronized
性能比同步代码块差,因为,同步代码块可以先执行一些操作,但是现在可以忽略不记,同步方法可读性更好
④方式三:Lock锁
每个类对象都应该有个自己的锁对象,所以定义实例变量Lock。
final代表了lk不可二次赋值
加锁解锁放在try-finally中的finally区中,这样就保证了不会出现中间出现问题不会进行解锁的操作
6.线程通信-了解
7.线程池
①认识线程池
若线程池中的数量固定,线程占满,任务会排队,待线程执行完之前操作会继续执行后续任务
②创建线程池
参数很重要
临时线程数量等于最大线程数量减去核心线程数量,核心线程会一直存在,线程工厂负责去创建临时线程
最大存活时间后跟了TimeUnit.SECONDS代表是秒,任务队列可以是:new LinkedBlockingQueue<>,但更多采用基于数组的new ArrayBlockingQueue<>(),线程工厂这是个创建默认线程工厂的方式,任务拒绝策略是使用了ThreadPoolExecutor的内部类,当最大线程数量都在工作,任务队列也满了就会抛异常给任务队列。
③线程池处理Runnable任务
临时线程会在核心线程都在工作,任务队列占满的情况下创建,超过临时创建的数量就会抛异常
任务拒绝策略
④线程池处理Collable任务
⑤Executors工具类实现线程池
核心线程数量配置选择:
注意:在大型并发系统环境中不使用工具类去创建线程池,因为任务队列是无限的,太多会瘫痪
8.并发和并行
①认识进程
CPU同一时间会执行多个线程,并行,CPU这多个线程不断切换,切换很快,导致看上去就是同时进行,并发
9.线程的生命周期
sleep方法不会释放锁,wait会把锁释放
10.悲观锁与乐观锁
悲观锁:一上来就加锁,没有安全感。每次只能一个线程进入访问完毕后,再解锁。
/乐观锁:一开始不上锁,认为是没有问题的,大家一起跑,等要出现线程安全问题的时候才开始控制。线程安全,性能较好。
CAS整数修改的乐观锁:
使用这种锁它会拿到共享资源对象的地址,然后通过地址得到此时需要修改的值的大小,拿期望修改的值在此处就是加一,与那个值进行比较如果不一样,就返回继续拿最新的值与修改的操作加一,直到此时要修改的值和期望值相同,再返回此时要修改的值是多少去加一。
就是判断此时要修改的值是否在我要修改的时被别人已经修改
11.线程应用
二、网络编程
CS\BS都依赖于网络编程
1.网络通信的三要素
IP地址就是设备在网络中的身份证,端口就是应用程序在设备中的身份证
①IP地址
IP域名,就是代表IP地址
IP常用命令在cmd输入
Java中代表IP地址的类:
这里的timeout代表这个时间内是否能联通
②端口号
③协议
我们要关注从应用层到传输层之间的协议
对于TCP协议:
三次握手建立可靠连接
服务器端收到客户端发出的连接请求,确保了客户端可以发消息;客户端收到服务器端返回的响应,确保了服务器端可以收到消息并且可以发消息;而服务器端再次收到客户端发出的确认信息,保证了客户端可以收到消息。
这样就确保了客户端和服务器端都可以收发消息,保证了可靠连接。
四次挥手确保断开连接
2.UDP通信
①入门
客户端的创建:
服务器端对象
服务端先启动,启动后会在receive方法这等待,如果有客户端发送消息才会继续往下
服务器端还可以拿到地址和端口
②多发多收
客户端如何修改
服务端如何改
3.TCP通信
①入门
服务端启动后在accept处等待,与客户端连接后,会在使用socket通信的字节输入流的时候停止等待。
②多发多收
③支持与多个客户端通信
服务器端读数据线程类:
主线程接受客户端:
④端口转发-群聊
服务器端主线程添加集合记录scoket
子线程发送给其他在线客户端方法:
子线程重写run方法,退出时应删除集合元素
客户端若想收消息,得有个子线程负责:
收消息线程类:
⑤BS架构
之前都是CS架构客户端-服务器端
BS架构,浏览器-服务器端
主线程接受浏览器连接:
子线程类:
浏览器是短连接响应后就需要关闭,由于得遵循HTTP协议格式
所以服务器端应该改造成:
太多人访问容易发生并发
使用线程池优化
其实可以不改这个类因为Thread类是实现Runnable的
三、Java高级
1.单元测试
Junit单元测试框架
业务方法:
Junit单元测试框架,断言机制通过
注解:
如果每个方法需要一个独立的通信管道就需要在Before和After中建立和释放资源
测试方法共用同一个通信管道,就在BeforeClass和AfterClass中建立和释放资源
2.反射
①认识反射
②获取类
③获取类的构造器
记记代码风格就行,后续有用
④获取类的成员变量
⑤获取了类的成员方法
⑥反射的作用、应用场景
反射做通用框架
3.注解
①认识注解
如果不止一个属性,但是其他都有默认值则也可以不写
②元注解
③注解的解析
④应用场景
5.动态代理
①创建代理
创建的接口表明了BigStar类要代理的方法,并且BigStar类应该实现这个接口。
代理:
②实际代理应用
统计耗时是相同代码且与业务无关
代理:
用户类
主程序调用: