A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

就业班JavaSE高级部分day07 线程间通信 线程池 Lambda表达式


等待唤醒机制:(线程之间的通信)
有效利用资源
wait和notify/notifyAll的执行原理:
wait:
        线程不再活动, 不再参与调度, 进入 wait set 中, 因此不会浪费 CPU 资源, 也不会去竞争锁, 这时的线程状态即是"WAITING". 它还要等着别的线程执行"通知(notify)", 让在锁对象上等待的线程从 wait set 中释放出来, 重新进入到调度队列(ready queue)中
notify/notifyAll:
        哪怕只通知了一个等待的线程, 被通知线程也不能立即恢复执行, 因为它当初中断的地方是在同步块内, 而
此刻它已经不持有锁, 所以它需要"再次尝试去获取锁"(很可能面临其它线程的竞争), 成功后才能在当初调用 wait() 之后的地方恢复执行
总结如下:
        如果能获取锁, 线程就从"WAITING"状态变成"RUNNABLE"状态
        否则, 从 wait set 出来, 又进入entry set, 线程就从"WAITING"状态又变成"BLOCKED"状态
吃包子案例:
C:/Users/Administrator/AppData/Local/YNote/data/weixinobU7VjkOlFOSrTPAb-ROkG2i_vds/37f5a84967ef477d959be3299ab0e292/e405cfd78ba84f20923453486b43ddfc.jpg
资源: 包子类
        属性:
                皮
                馅
                是否有包子: true有, false没有
生产者: 包子铺类, 继承Thread
        任务:
                对包子状态进行判断:
                true: 有包子, 则wait()
                false: 没有包子, 则交替生产不同皮和馅的包子, 修改包子状态为true, 并notify()吃货来吃
消费者: 吃货类, 继承Thread
        任务:
                对包子状态进行判断:
                false: 没有包子, 则wait()
                true: 有包子, 则吃, 修改包子状态为false, 并notify()包子铺生产
测试类:
        创建包子对象(作为共享的锁对象)
        创建包子铺对象, 启动线程
        创建吃货对象, 启动线程
线程池概念和原理:
普通创建线程方式的缺点:
"创建"线程和"销毁"线程都是比较占用内存和CPU的操作.
对于一些数量多, 执行时间短的任务, 频繁的创建和销毁线程来执行, 会降低程序运行效率.
线程池
一个容纳多个线程的容器(集合)
其中的线程可以反复使用, 省去了频繁创建线程对象的操作, 无需反复创建线程而消耗过多资源
提前创建好多个线程对象, 放在集合中. 多个任务来了反复使用这些线程对象来执行
线程池的创建和使用步骤:
1. 使用Executors的静态方法 newFixedThreadPool(int nThreads) 创建线程池ExecutorService
2. 创建一个任务类, 实现Runnable接口, 重写run()方法
3. 调用ExecutorService对象的 submit(Runnable task) 方法, 传递任务给线程池, 执行任务
4. 调用ExecutorService对象的 shutdown() 方法, 销毁线程池 (不建议执行)
函数式编程思想: Lambda表达式:
函数式编程思想:
面向对象: 强调"用哪个对象的哪个方法"来做事 (注重语法形式: 继承 方法重写)
函数式: 强调"传入的参数 要执行的代码"
函数式编程的好处:
        简化代码编写 (使用 λ Lambda表达式, 简化匿名内部类的代码)
Lambda标准格式
Lambda表达式的3个部分:
1. 一些参数 ()
接口中抽象方法的参数列表. 没参数就空着; 有参数就写, 多个参数用逗号分隔
2. 一个箭头 ->
将参数传递给方法体
3. 一段代码 {}
重写接口抽象方法的方法体
格式:
// 写成多行
        (数据类型 变量名, 数据类型 变量名) -> {
        一些重写方法的代码
        一些重写方法的代码
        ...
    }
        // 如果代码只有一行, 也可以合并写成一行
        (参数列表) -> {一些重写方法的代码}
Lambda表达式的使用前提:
    1. Lambda只能用于接口, 且"接口中有且仅有一个抽象方法"(也称为"函数式接口")
        普通类, 抽象类不能用
    2. 使用Lambda必须具有上下文推断
        接口中只能有一个抽象方法, 才能推断出来重写的是这个抽象方法
    简而言之: 参数类型必须是函数式接口

0 个回复

您需要登录后才可以回帖 登录 | 加入黑马