javase 多线程
一、多线程
(一)创建多线程的三种方法
1、继承Thread类,重写run()方法

注意:一定要调用线程对象的start方法,如果调用run方法,JAVA会把它看成一个普通的线程。
2、实现Runnable接口,重写run()方法

举例:

写法二、匿名内部类:

写法三、lambda表达式
3、实现Callable接口
前两种方法主线程拿不到子线程的返回值。
而第三种方法可以。


举例:

(省略MyCallable的定义代码,其中还写了MyCallable的有参构造函数,这样就可以对其进行传参了。)
那么,为什么不直接把FutureTask的功能给Callable呢?为什么还要多加一层?
gemini的回答:
总结

(二)线程的常用方法

(三)线程同步
1、同步代码块

synchronized()括号中的对象相当于是信号量
使用规范

2、同步方法

举例

同步代码块和同步方法的区别
- 同步代码块锁的范围更小,性能更好
- 同步方法的可读性更好,实现更简单
3、Lock锁
相比前两种更加灵活。

1 | // 创建锁对象 |
注意
- 锁对象最好用final修饰,防止其他人修改
- 释放锁的代码最好写在finally代码块中,保证无论是否出错,最后都会释放锁(
try{} finally{})
(四)线程池
为什么需要线程池?
如果没有线程池,用户每发出一个请求,后台就需要创建一个新的线程来处理。
创建新线程的开销很大,并且请求过多时,会产生大量的线程,严重影响性能。
1、创建线程池对象
1️⃣使用ExecutorService的实现类ThreadPoolExecutor


ExecutorService接口的常用方法

执行Runnable任务

执行Callable任务

注意事项
1、什么时候创建临时线程?
核心线程都忙 + 任务队列已满 + 还可以创建临时线程
2、什么时候拒绝新任务?
核心线程和临时线程都忙 + 任务队列已满
任务拒绝策略

2️⃣使用工具类Executors创建线程池对象(不建议使用)

注意

