多线程实现方式
-
继承Thread类
- 创建类继承自
Thread
。 - 重写
run
方法,实现线程逻辑。 - 调用
start
方法启动线程。
- 创建类继承自
-
实现Runnable接口
- 创建类实现
Runnable
接口。 - 重写
run
方法,实现线程逻辑。 - 创建
Thread
对象,传入Runnable
实现类实例,调用start
方法。
- 创建类实现
多线程方法
start()
: 启动线程。setPriority()
: 设置线程优先级。setDaemon()
: 设置守护线程。yield()
: 礼让线程,可能让其他线程执行。join()
: 等待线程执行完毕。
多线程生命周期
- 创建线程后调用
start
获得执行资格,但无执行权。 - 抢到执行权后执行
run
方法,执行完毕后线程结束。 - 使用
sleep
或阻塞方法后,线程进入阻塞状态,结束后回到就绪状态。
同步与锁
synchronized
: JVM层面实现,可在类或方法上使用。Lock
: JDK层面实现,只能在方法中使用,性能更高。wait
与sleep
:wait
用于线程间协调,释放锁;sleep
不释放锁。
线程池
-
线程池参数:
- 当前线程数
- 最大线程数
- 临时线程空闲时间
- 时间单位
- 线程排队数量
- 拒绝策略
- 创建线程的方式
-
任务提交流程:
- 判断当前线程数是否小于核心线程数,是则创建线程并执行任务。
- 大于核心线程数则将任务放入阻塞队列。
- 队列满且当前线程数小于最大线程数时,创建新线程执行任务。
- 队列满且当前线程数等于最大线程数时,执行拒绝策略。
-
线程池状态:
- Running: 接受新任务,处理队列任务。
- Shutdown: 不接受新任务,处理队列任务。
- Stop: 不接受新任务,不处理队列任务。
- Tidying: 线程停止后的状态。
- Terminated: 线程池完全停止。
线程池核心与最大线程数设置
- CPU密集型任务:核心数+1。
- IO密集型任务:2*核心数。
- 根据线程等待时间与运行总时间设置线程数。
避免死锁
- 注意加锁顺序,设置超时时间,检查死锁,避免两个锁互持资源。
Java并发可见性问题
- 使用
volatile
关键字避免CPU缓存导致的可见性问题。
HashMap扩容机制
- Java 1.7: 初始容量16,2倍扩容。
- Java 1.8: 链表转红黑树,超过8个元素生成新的红黑树。
锁类型
- 非公平锁:可能后来先得。
- 公平锁:按顺序排队。
- 偏向锁:单线程访问时提高效率。
- 自旋锁:轻量级锁,多次自旋后升级为重量级锁。
ThreadLocal
- 底层为Map集合,使用时注意内存泄漏问题,使用后调用
remove
方法。
可重入锁
- 同一线程可重复获得锁对象。
start与run方法区别
start
启动新线程,run
只是普通方法调用。start
实现多线程,run
没有。start
不可重复调用,run
可以。start
允许线程切换,run
需等待执行完毕。