学习多线程
学习多线程1.认识程序,进程,线程
程序
程序由指令和数据组成,是静态的
进程
启动一个程序,就启动了一个进程。
进程就是程序的一次执行过程。
进程是动态的。
线程
一个进程包含多个线程。例如:播放视频时,有动画,有声音,有弹幕……
2.如何创建线程
继承Thread类
三板斧:
[*]继承Thread类
[*]重写run方法
[*]启动线程
实现Runnable接口
四板斧:
[*]实现Runnable接口
[*]重写run方法
[*]将线程对象放入Thread对象
[*]启动Thread对象的线程
实现Callable接口
https://img2023.cnblogs.com/blog/3264156/202309/3264156-20230916140454226-2054295196.png
3.静态代理模式
一个关于结婚的例子
You you = new You();
WeddingFirm wf = new WeddingFirm(you);
wf.marry();
//You类,WeddingFirm类都实现了Marry接口,也就都实现了marry方法代入到线程
MyThread mt = new MyThread();
Thread t = new Thread(mt);
t.start();
//MyThread 类,Thread 类都实现了 Runnable 接口,也就都实现了 run 方法4.lambda表达式
函数式接口
函数式接口
只包含一个抽象方法的接口。一个典型的函数式接口:Runnable接口
逐步简化
[*]外部类
[*]静态内部类
[*]局部内部类
[*]匿名内部类
[*]lambda表达式
[*]去参数类型
[*]去小括号
[*]去大括号
lambda语法
(参数列表) -> {实现抽象方法的方法体}
参数列表
[*]有一个参数,不需要小括号
[*]没有参数,或有多个参数必须加小括号
[*]参数类型要省略就全省略。为什么可以省略?Java会去检查运行类型(即函数式接口)的方法。
方法体
[*]只有一条语句:无论有没有返回值都不需要大括号。如果写了return,就一定要加大括号。
[*]有多条语句:一定要加大括号
举例:
Thread thread = new Thread(() -> System.out.println("Hello World!")).start();new Thread(Runnable) 构造方法中可以放入一个对象,这个对象必须是实现了Runnable接口的对象
扩展:
new 代理类(实现了 任意函数式接口的 匿名内部类 对象)
5.线程状态
线程状态
https://img2023.cnblogs.com/blog/3264156/202309/3264156-20230916140908264-1746092132.png
https://img2023.cnblogs.com/blog/3264156/202309/3264156-20230916140956110-447751949.png
线程方法
https://img2023.cnblogs.com/blog/3264156/202309/3264156-20230916141102854-310236225.png
线程停止
推荐使用 设置标志位 的方式,如flag =true/false
https://img2023.cnblogs.com/blog/3264156/202309/3264156-20230916141138311-602786273.png
线程休眠
https://img2023.cnblogs.com/blog/3264156/202309/3264156-20230916141208248-1218512312.png
线程礼让
https://img2023.cnblogs.com/blog/3264156/202309/3264156-20230916141232707-2089558241.png
线程插队
https://img2023.cnblogs.com/blog/3264156/202309/3264156-20230916141304793-1091086951.png
监测线程状态
https://img2023.cnblogs.com/blog/3264156/202309/3264156-20230916141332401-992870072.png
线程优先级
https://img2023.cnblogs.com/blog/3264156/202309/3264156-20230916141436878-1127663898.png
守护线程
https://img2023.cnblogs.com/blog/3264156/202309/3264156-20230916141506088-1283768961.png
6.线程同步
同步机制
先了解一个名词:并发
并发
多个线程想要获得(或操作)某个对象(或者某个资源),这种情况就叫做并发。但是当他们同时操作这个对象时,会有异常发生,例如:抢票问题(某一张票),取钱问题(某一张银行卡)。
这时,就要想些办法,来避免这些异常发生,于是,线程同步机制就出现了。说白了,线程同步是一种办法(或机制),这种办法,就是为了解决并发的问题。
于是,解决并发的问题,就变成了如何实现线程同步的问题。
同时和同步的区别:
同时和同步在含义和用法上有明显的区别。
同时强调的是时间因素,指的是在同一时刻,两个或多个事件同时发生。例如,当我们说“同时出发”时,指的是在某一特定的时间点,所有人或物都开始行动。
同步则不同,它更多地强调的是事件之间的协调性和一致性,而非单纯的时间因素。例如,在舞蹈表演中,每个舞者需要按照同样的节拍和步伐来表演,这就是同步。也就是说,所有舞者需要在时间和动作上保持一致,才能达到同步的效果。
以上是同时和同步的主要区别,希望对你有所帮助。
上面的解释来自于百度文心一言。
https://img2023.cnblogs.com/blog/3264156/202309/3264156-20230916141541293-565958557.png
队列和锁
光有队列,不一定安全。正在打饭的人得到一个锁,才能打饭,打完了饭,就释放掉锁,后面的人继续获取锁,继续打饭……
如果没有锁,前面的人还没打完饭,后面的人就迫不及待地也要打饭,于是,可能就打起来了……所以,队列加锁很有必要。
https://img2023.cnblogs.com/blog/3264156/202309/3264156-20230916141610485-908986081.png
队列和锁解决了线程同步的安全性
同步锁
synchronized 同步锁
https://img2023.cnblogs.com/blog/3264156/202309/3264156-20230916141636761-245927401.png
同步方法
https://img2023.cnblogs.com/blog/3264156/202309/3264156-20230916141706068-628233149.png
同步方法弊端
https://img2023.cnblogs.com/blog/3264156/202309/3264156-20230916141742242-392964212.png
同步块
https://img2023.cnblogs.com/blog/3264156/202309/3264156-20230916141809709-1869248582.png
死锁
https://img2023.cnblogs.com/blog/3264156/202309/3264156-20230916141849244-723795990.png
释放死锁:
https://img2023.cnblogs.com/blog/3264156/202309/3264156-20230916142145104-1603890676.png
死锁概念:
https://img2023.cnblogs.com/blog/3264156/202309/3264156-20230916141926355-1783351081.png
避免死锁:
https://img2023.cnblogs.com/blog/3264156/202309/3264156-20230916142214298-1843614531.png
Lock锁
Lock锁的概念
https://img2023.cnblogs.com/blog/3264156/202309/3264156-20230916142249712-2131551116.png
自定义lock锁
https://img2023.cnblogs.com/blog/3264156/202309/3264156-20230916142318181-1676026384.png
synchronized与lock对比
https://img2023.cnblogs.com/blog/3264156/202309/3264156-20230916142347542-820914061.png
7.线程通信
生产者与消费者模式
https://img2023.cnblogs.com/blog/3264156/202309/3264156-20230916142422737-1390999386.png
线程通信问题分析
https://img2023.cnblogs.com/blog/3264156/202309/3264156-20230916142444820-1877985236.png
解决线程通信的方法
https://img2023.cnblogs.com/blog/3264156/202309/3264156-20230916142522225-1845220166.png
模型1:
https://img2023.cnblogs.com/blog/3264156/202309/3264156-20230916142551447-327737839.png
管程法代码实现
package thread.communication;/** * 测试生产者与消费者模式:利用缓冲区解决(管程法) * 需要生产者,消费者,产品,缓冲区 */public class TestPC { public static void main(String[] args) { SynContainer synContainer = new SynContainer(); new Producer(synContainer).start(); new Consumer(synContainer).start(); }}//消费者class Consumer extends Thread { SynContainer synContainer; public Consumer(SynContainer synContainer) { this.synContainer = synContainer; } @Override public void run() { for (int i = 1; i
页:
[1]