一、线程简介
1、多任务
2、多线程
多线程:让几个方法同时执行
3、普通方法调用和多线程
多线程的效率更高
4、程序、进程、线程
5、process与thread
进程是系统资源分配的单位
线程是CPU调度和执行的单位
6、核心概念
main为主线程
main函数叫做用户线程,gc线程(JVM给的)叫做守护线程
多线程的目的:就是可以同时执行多个方法
二、线程实现(重点)
1、线程创建 (Thread、Runnable、Callable)
thread类实现了runnable接口
2、Thread
1)简介
2)部分文档
3)demo
注意:调用run、start方法产生的结果是不同的。
线程不一定立即执行,CPU安排调度
注意:是调用start开启线程,而不是run方法
4)小例子:使用多线程下载图片
运行结果:
3、实现runnable
1)简介
2)部分文档
3)demo
//创建线程对象,通过线程对象来开启我们的线程,【代理】
// Thread thread=new Thread(testThread3);
// thread.start();
//合并为下:
new Thread(testThread3).start();
4)案例
4、小结
使用runnable接口的好处:
-
避免单继承的局限性,方便同一个对象被多个线程使用
-
一份资源,多个代理
5、并发问题demo
运行结果:
6、龟兔赛跑例子
7、callable接口
1)简介
2)demo
8、静态代理
1)简介
2)demo
运行结果:
3)lambda表达式
任何一个接口,如果只包含唯一一个抽象方法,那么他就是一个函数式接口,对于函数式接口,可以通过lambda表达式来创建该接口的对象。
1、一般实现
2、静态内部类的实现
3、局部内部类实现
4、匿名内部类实现
5、用lambda简化
6、另一个demo
多个参数的时候:
runnable是函数式接口,可以使用lambda表达式来进行简化
三、线程状态
1、五大状态
2、线程停止
1)简述
推荐线程自己停下来,
建议使用一个标志位让线程停下来
2)demo
运行结果:
注意:一定要让线程自己停下来
3、线程休眠-》sleep
1)简述
时间的单位是毫秒
sleep会有异常,需要抛出
每个对象都有一把锁,sleep不会释放锁
2)demo1:模拟网络延时
主要的作用:放大问题的发生性
会有-1
3)demo2:模拟倒计时
4、线程礼让-》yield
1)简述
让正在执行的程序暂停,但不阻塞,让线程从运行状态转化为就绪状态,让CPU在重新进行调度。
2)demo
礼让成功:
礼让不成功:
4、线程强制执行-》join
1)简述
可以想象成插队
2)demo
运行结果:
当main线程到200的时候,会让testJoin强制插队,对把testJoin执行完才会返回执行main线程
5、观测线程状态
1)简述
2)demo
线程一旦进入死亡状态,就不能再次启动了。
6、线程优先级
1)简述
性能倒置
2)demo
运行结果:
注意:先设置优先级,再启动
7、守护线程
1)简述
main -》用户线程
gc-》守护线程
2)demo
运行结果:
四、线程同步(重点)
1、线程同步机制
多个线程操作同一个资源
并发问题-》线程同步-》线程同步其实是一种等待机制
对象等待池
每个对象都有一把锁,sleep不会释放锁。
线程同步需要:队列+锁 -》安全
2、三大不安全案例
1)demo1
每个线程都在自己的工作内存交互,内存控制不当会造成数据不一致
2)demo2
sleep可以放大问题的发生性
3)demo3
3、同步方法及同步块
1)简述
只有修改代码才需要锁
2)demo1
3)demo2
4)demo3
synchronized块 锁住的对象是需要增删改的对象即可
5)copyonwriteArrayList
4、死锁
1)简述
2)demo
运行结果:
出现死锁
修改:
解决方法:就是不要让一个资源拿对方的锁就可以解决了。
3)死锁避免
5、Lock锁
1)简述
显式
2)reentrantLock 可重入锁
3)demo
运行结果:
4)synchronized与lock的对比
五、线程通信问题
1、生产者和消费者问题
2、解决方法:管程法
利用缓冲区解决:管程法
运行结果:
注意:要使用while,而非if,不然会出现脏读
3、解决方法:信号灯法
信号灯法:标志位解决
运行结果:
六、线程池
1、概念
2、demo
运行结果:
七、总结
1)回顾线程的创建
运行结果:
2)同步
synchronized、lock等