【Java SE进阶】Day07 等待与唤醒案例、线程池、Lamdba表达式
一、等待唤醒机制
1、线程间通信
- 多个线程处理同一个资源,就存在线程通信问题(线程间存在竞争与协作机制)
- 为什么处理:为了 保证多个线程有规律地完成同一任务
- 如何处理:避免对共享变量争夺,需要等待唤醒机制,保证各线程有效利用资源
2、等待唤醒机制
- 定义:A线程执行操作后进入等待(wait)状态,等B线程执行完指定代码后再将A唤醒(notify)/唤醒多个线程(notifyAll)
- 注意:
- wait和notify需要由同一个锁对象Obj调用
- 锁对象可以是任意对象<? extends Object>
- wait和notify必须在同步代码块或同步方法中使用(必须由锁对象调用)
3、生产者与消费者问题【线程之间的通信】
- 等待唤醒机制就是生产者与消费者问题
二、线程池
1、概念
- 使用时频繁创建线程会降低系统效率
- 实际上是一个集合,建议使用LInkedList
- 好处:降低资源消耗、提高响应速度(无需每次进行线程创建)、可以根据系统承受能力调整工作线程数目
2、使用
- 线程池的工厂类java.util.concurrent.Executors,用于生成线程池
- 静态方法:ExecutorService newFixedThreadPool(int nThreads)
- 线程池的接口java.util.concurrent.ExecutorService,获取接口调用start方法
- submit(Runnable task):提交线程任务用于执行
- shutdown():销毁线程池
- 使用步骤:
package com.liujinhui.Day1101WaitAndNotify; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class ThreadPool { public static void main(String[] args) { // 1.使用工厂类java.util.concurrent.Executors的静态方法newFixedThreadPool生成一个指定数量的线程池 ExecutorService es= Executors.newFixedThreadPool(2); // 3.调用ExecutorService中的方法submit,传递线程任务,开启线程,执行run方法 es.submit(new RunnableImpl()); //线程池会一直开启,使用完了线程,会自动把线程归还给线程池,线程可以继续使用 es.submit(new RunnableImpl()); es.submit(new RunnableImpl()); es.shutdown(); es.submit(new RunnableImpl());//线程池没有了,就不能获取线程了 }}
三、Lambda表达式
函数内调用了某接口的抽象方法,参数为接口名
1、函数式编程思想
- 强调解决问题得到结果,不重视具体解决的过程
- 面向对象:强调可以解决问题的对象
2、冗余的Runnable代码
- 函数内调用Runnable的run方法
- 原来:实现类重写Runnable的run方法
- 简化:匿名内部类
3、编程思想转换
- 将面向对象编程思想转换为函数式编程思想
- 与面向过程相比,更注重结果而非过程
- 真实目的 :传递一段代码
4、Lambda写法(JDK8的新特性)
- 打开了函数式编程思想的大门
package com.liujinhui.Day1101WaitAndNotify; public class Demo02Lambda { public static void main(String[] args) { //之前,匿名内部类 new Thread(new Runnable(){ @Override public void run(){ System.out.println(Thread.currentThread().getName()+"正在执行接口"); } }).start(); //现在,使用Lambda表达式实现多线程 new Thread(()-> System.out.println(Thread.currentThread().getName()+"正在执行接口") ).start(); } }
5、Lambda标准格式
package com.liujinhui.Day1101WaitAndNotify; import java.util.Arrays; import java.util.Comparator; public class Demo01Arrays { public static void main(String[] args) { //使用数组存储多个Person对象 Person[] person={new Person("柳岩",38), new Person("迪丽热巴",18), new Person("古力娜扎",19)}; //升序排列,使用Arrays的sort方法 Arrays.sort(person, new Comparator<Person>() { @Override public int compare(Person o1, Person o2) { return o1.getAge()-o2.getAge(); } }); for (Person person1 : person) { System.out.println(person1); } //使用Lambda表达式,简化匿名内部类 Arrays.sort(person,(Person o1,Person o2)->{return o1.getAge()-o2.getAge();}); for (Person p : person) { System.out.println(p); } } }
6、Lambda省略格式
- 可省略内容:可以根据上下文推导出来的
- 参数列表类型
- 参数列表的个数为一个时,可省略括号
- 省略大括号、return和分号
- 要省略必须一起省略
//使用Lambda表达式,简化匿名内部类 Arrays.sort(person,(Person o1,Person o2)->{return o1.getAge()-o2.getAge();}); //省略优化Lambda Arrays.sort(person,(o1,o2)-> o1.getAge()-o2.getAge());
7、使用前提
- 函数式接口(接口中只有一个抽象方法),如Runnable的run方法、Comparator的sort方法
- 具有上下文推断(方法的参数类型必须为Lambda对应的接口类型)
本文来自博客园,作者:哥们要飞,转载请注明原文链接:https://www.cnblogs.com/liujinhui/p/14826690.html