1、 线程池
什么是线程池?一个用来创建和管理线程的容器。
- 线程池的原理
线程复用
- 线程池好处
1、降低了资源的消耗,避免了频繁创建和销毁线程带来的系统开销
2、提高了响应速度
3、可以更好的管理线程的数量
1.1 线程池的使用:提交了Runnable任务
1.1.1 如何获得线程池
通过该类的静态方法可以创建线程池对象,该方法如下:
public static ExecutorService newFixedThreadPool(int nThreads) //创建线程池对象并制定线程数量
参数 ExecutorService: 该接口的实现类对象就是一个线程池对象
ExecutorService常用方法:
Future<?> submit(Runnable task)
提交一个可运行的任务执行,并返回一个表示该任务的Future。
1.1.2 销毁线程池
void shutdown() //销毁线程池,会等待线程池中所有的任务执行完毕之后再销毁
shutdownNow() //立即销毁线程池,如果还没有开始执行的任务就不会执行
1.2 线程池的使用:提交了Runnable任务
-
通过工具类ExecutorService调用静态方法:newFixedThreadPool创建线程池对象并制定线程的数量。
-
创建一个类实现Runnable接口,重写run方法,将线程任务相关的代码写在run方法中
-
调用线程池对象的submit方法,提交任务
-
关闭线程池(一般不做)
-
1.3 线程池的使用:提交了Callable任务
-
通过工具类ExecutorService调用静态方法:newFixedThreadPool创建线程池对象并制定线程的数量。
-
创建一个类实现Callable接口,重写call方法,将线程任务相关的代码写在call方法中
-
调用线程池对象的submit方法,提交任务
-
关闭线程池(一般不做)
1.4 Callable接口和Runnable接口的区别:
Callable接口中call方法有返回值,可以声明异常
Runnable接口中的run方法没有返回值,不能声明异常(编译时异常)
1.5 Callable接口和Runnable接口选择:
判断任务执行完毕之后是否需要有一个返回值给调用者。如果需要,选择Callable;如果不需要,两个都可以。
2、 线程等待与唤醒机制概述
又称为线程间通信。两个或多个线程在执行任务过程中相互协作共同完成任务。
2.1 线程等待与唤醒机制相关方法
void wait(); //等待,让当前正在执行的线程释放CPU使用权,进入等待状态
void notify(): //唤醒,随机唤醒一个正在等待的线程,让其进入可运行状态
void notifyAll(); //唤醒所有正在等待的线程,让其进入可运行状态
这三个方法必须由锁对象调用且必须在同步代码块或同步方法中调用。
3、 Lambda表达式
3.1 Lambda表达式概述
函数式编程思想的体现。函数式编程思想则尽量忽略面向对象的复杂语法——强调做什么,而不是以什么形式做。
Lambda表达式是JDK1.8新特性
Lambda表达式可以简化匿名内部类复杂代码编写。只专注做什么,而不是怎么做。
3.2 Lambda 表达式格式
3.2.1 Lambda表达式的标准格式:
3.2.1.1 格式:(数据类型 参数…) -> {//方法体},也叫匿名函数
说明:
():等价于方法的参数列表
-> :新语法,固定写法,代表指向,小括号中参数可以在方法体中使用
{}:等价于方法体
3.2.1.2 Lambda表达式的使用前提条件:
必须是接口且接口中只有一个抽象方法
3.2.1.3 Lambda表达式的原理:
创建了接口的实现类对象,重写了接口中的抽象方法
3.2.2 Lambda表达式省略格式:
格式:(参数…) -> {//方法体}
省略规则如下:
小括号中的参数类型可以省略,不管有几个参数
如果小括号中只有一个参数,可以省略小括号
如果方法体中只有一条语句,则可以省略大括号;如果省略了大括号,则return语句和分号必须要省略。
4. 使用线程注意事项
-
把多线程共享的数据、变量放在类里面的成员变量里去定义,且定义成static。
-
把各个线程私有的统计数据、变量放在run方法里面定义。这是因为各个线程是new 出来的,都拥有各自run方法里面的局部变量。