> 并发编程三要素
原子性:共享资源写操作,其他线程只能看到结果。加锁、CAS实现
可见性:多线程共享变量,线程修改变量后,其他线程可以立即看到修改的结果。Synchronized、Lock 方法保证任意时刻只有一个线程获取锁,锁释放前把最新值刷新到主内存。volatile 保证可见性
有序性:程序执行,为了提高性能,存在编译器和处理器对指令重排问题。volatile 实现
> 线程安全和非线程安全
线程安全:多线程操作同一个对象不会有问题,synchronized实现线程同步
非线程安全:多线程操作同一个对象可能出现问题
> 线程的生命周期
新建:创建线程,进入新建状态
就绪:调用 start()进入就绪状态,线程做好准备,等待CPU调度
运行:线程得到系统资源,进入运行状态
阻塞:线程因某种原因放弃CPU使用权,停止运行
1.等待阻塞:运行状态调用 wait()进入等待阻塞状态,调用 notify()唤醒线程
2.同步阻塞:线程获取同步锁失败,进入同步阻塞状态
3.其他阻塞:调用 sleep()进入休眠阻塞状态。sleep()超时、IO处理完成,进入就绪状态
死亡:线程执行完/异常退出,进入死亡状态
先调用start再执行run是多线程,直接执行run成为主线程下的普通方法执行
一个线程多次调用start抛出异常
> 线程池优点
重用线程,避免线程频繁创建和销毁,提高响应速度,减少资源消耗
控制最大并发线程数,提高系统资源利用率,避免资源竞争、阻塞
提供定时执行、定期执行、单线程、并发数控制功能,统一分配、调优、监控
> 线程池创建方式
1.ThreadPoolExecutor 推荐,明确线程池参数设置、运行规则,规避资源耗尽。指定BlockQueue容量,提交线程数超过可用线程数时抛出异常,使用有边界队列,队列满了无法处理新请求
ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler) 核心线程数-最大线程数-空闲线程存活时间-单位-阻塞队列-线程工厂-饱和策略
2.Executors 类不推荐,线程池类型[单个线程的线程池、固定线程数量的线程池、无限线程数量的线程池、可缓存的线程池]
> 线程池状态
ThreadPoolExecutor 类的线程池状态 Running Shutdown Stop Terminated
Running 运行状态,接收提交任务,处理阻塞队列中的任务
Shutdown 不接收提交任务,可以处理阻塞队列任务,shutdown()线程池进入关闭状态
Stop 不接收提交任务,不能处理阻塞队列中的任务,中断处理任务的线程。shutdownNow()线程池进入该状态
Tidying 任务全部终止,有效线程数为0[阻塞队列空,工作线程0],线程池进入该状态
Terminated 调用 terminated()线程池进入该状态
线程池创建后处于 Running 状态
调用 shutdown()处于 Shutdown 状态,不接收新任务,等待缓冲队列的任务完成
调用 shutdownNow()处于 Stop 状态,不接收新任务,并终止执行的任务
Shutdown 或 Stop 状态,且所有工作线程已销毁,任务缓存队列已清空或执行结束,线程池设置为 Terminated 状态
> 阻塞队列
阻塞队列空,线程去取阻塞。阻塞队列满,线程添加阻塞。自动阻塞队列和唤醒队列
ArrayBlockingQueue 数组结构的有界阻塞队列,按FIFO排序元素
LinkedBlockingQueue 链表结构的有界阻塞队列,按FIFO排序元素,不推荐
LinkedBlockingDeque 链表结构的双向阻塞队列
PriorityBlockingQueue 具有优先级的无界阻塞队列
DelayBlockingQueue 使用优先级队列实现的延迟无界队列
SynchronousQueue 不存储元素的阻塞队列(单个元素的队列)插入时等另一个线程调用移除,否则处于阻塞状态
LinkedTransferQueue 链表结构的无界阻塞队列
> 提交任务,线程池队列满会发生什么
无界队列 LinkedBlockingQueue,添加新任务到阻塞队列中等待执行,可以无限存放任务
有界队列 ArrayBlockingQueue,添加新任务到队列,队列满了,增加线程数量/饱和拒绝策略
> 关闭线程池,遍历线程池中的工作线程,对每个工作线程调用 interrupt 中断线程
shutDown 将线程池的状态设置成 SHUTDOWN,正在执行的任务继续执行,没有执行的任务将中断
shutDownNow 将线程池的状态设置成 STOP,正在执行的任务停止,没有执行的任务返回
> 线程池执行原理
创建线程池,提交任务
线程数量<corePoolSize,创建核心线程运行任务,线程超时不会销毁
线程数量>corePoolSize,任务放入阻塞队列
阻塞队列满了,线程数量<maximumPoolSize,创建非核心线程运行任务,执行任务后线程不会销毁,去阻塞队列拿任务执行,拿任务时阻塞,超时返回null且销毁当前线程,直到线程数=corePoolSize后不会线程销毁
阻塞队列满了,线程数量>maximumPoolSize,线程池抛出异常
> 线程池饱和策略
AbortPolicy 默认中止并抛出异常
CallerRunsPolicy 调用者线程执行任务
DiscardOldestPolicy 丢弃阻塞队列最近一个任务,执行当前任务
DiscardPolicy 丢弃当前任务,不抛出异常
> 线程池的注意事项
线程池提高并发性能,不合理使用,容易导致死锁、系统资源不足、线程泄漏
合理设置线程数,CPU密集型任务,参考值设为 NCPU+1。IO密集型任务,参考值设置为 2*NCPU