day07【线程池、Lambda表达式】
主要内容
- 等待与唤醒案例
- 线程池
- Lambda表达式
教学目标
- 能够理解线程通信的概念 Java中线程池运行原理 -[ ] 能够理解函数式编程相对于面向对象的优点 Lambda标准格式的表达式 Lambda使用标准格式Runnable与Comparator接口 Lambda表达式省略格式和规则 Lambda省略格式使用Runnable与Comparator接口 通过Lambda标准格式采用自定义接口(有,只有抽象方法) 通过Lambda使用自定义接口的省略格式(只有一种抽象方法) Lambda两项使用前提
第一章 等待唤醒机制
1.1 线程间通信
**概念:**多线程处理相同的资源,但处理动作(线程任务)不同。
比如:线程A线程用于生成包子B包子可以理解为相同的资源和线程A与线程B处理动作,一个是生产,一个是消费,所以线程A与线程B线程通信存在问题。
[外链图片存储失败,源站可能有防盗链机制,建议保存图片直接上传(img-fNyhi81w-1642046309400)(img\线程间通信.bmp)]
多线程并发执行时,默认情况下CPU它是随机切换线程的。当我们需要多个线程来共同完成一项任务,并且我们希望它们能够定期执行时,需要多个线程之间的协调通信,以帮助我们共同操作多个线程的数据。
在处理相同的资源和不同的任务时,多个线程需要线程通信来帮助解决线程之间使用或操作相同的变量。也就是说,当多个线程操作相同的数据时,避免争夺相同的共享变量。也就是说,我们需要使每个线程能够有效地利用资源。这种方法是
1.2 等待唤醒机制
这是多线程之间的一种机制。说到线程,我们经常想到线程之间的线程,例如,争夺锁,但这不是故事的全部,线程之间会有合作机制。就像你和你的同事在公司一样,你在晋升时可能会有竞争,但更多的时候,你更多的是一起完成一些任务。
规定线程操作后,进入等待状态(),等待其他线程执行其指定代码,然后唤醒它();如果需要多个线程等待,可以使用 notifyAll()唤醒所有等待线程。
wait/notify 是线程间的合作机制。
等待唤醒机制是用来解决线程间通信问题的,三种方法的含义如下:
- wait:线程不再活动,不再参与调度,进入 wait set 中,所以不会浪费 CPU 资源,也不会去竞争锁,此时的线程状态是 WAITING。它还等待其他线程执行一个,也即是“从这个对象上等待的线程wait set 释放出来,重新进入调度队列(ready queue)中
- notify:选择通知对象 wait set 释放线程;比如餐厅有空位置后,等待时间最长的顾客先入座。
- notifyAll:通知对象对象 wait set 上的所有线程。
注意:
即使只通知一个等待线程,通知线程也不能立即恢复执行,因为它最初中断在同步块内,现在它不再持有锁,所以她需要再次尝试获得锁(可能面临其他线程的竞争),成功调用 wait 方法后的地方恢复执行。
总结如下:
- 如果能获得锁,线程将从 开始WAITING 状态变成 RUNNABLE 状态;
- 否则,从 wait set 出来,再进 entry set,线程就从 WAITING 状态又变成 BLOCKED 状态
- wait方法与notify该方法必须由同一锁对象调用。因为:相应的锁对象可以通过notify唤醒使用同一锁对象调用的唤醒wait方法后的线程。
- wait方法与notify方法是属于Object类的方法。因为:锁对象可以是任何对象,任何对象的类别都继承了Object类的。
- wait方法与notify该方法必须用于同步代码块或同步函数。因为:这两种方法必须通过锁定对象来调用。
1.3 生产者和消费者的问题
等待唤醒机制实际上是生产者和消费者的经典问题。
以生产包子消费包子为例,等待唤醒机制如何有效利用资源:
包子铺设线程生产包子,食品线程消费包子。当包子没有时(包子的状态是false),等待吃货线程,生产包子(即包子状态为)true),并通知吃货线程(解除吃货的等待状态),因为已经有馒头了,所以馒头线程进入了等待状态。接下来,美食家线程是否能进一步实施取决于锁的获取情况。如果美食家被锁上,那么吃馒头,吃馒头(馒头的状态是false),并通知包子铺线程(解除包子铺等待状态),吃货线程进入等待。包子铺线程能否进一步执行,取决于锁的获取情况。 包子资源:
public class BaoZi { String pier ; String xianer ; boolean flag = false ;///包子资源 是否存在 包子资源状态} 吃货线程:
public class ChiHuo extends Thread{