本文主要介绍
- Java线程池(ThreadPool)
- FixedThreadPool
- CachedThreadPool
- ScheduleThreadPool
- SingleThreadExecutor
- SingleThreadScheduledExecutor
- ForkJoinPool
- 拒绝策略
- AbortPolicy
- DiscardPolicy
- DiscardOldestPolicy
- CallerRunsPolicy
- 阻塞队列(WorkQueue)
- LinkedBlockingQueue
- ArrayBlockingQueue
- SynchronousQueue
- ConcurrentLinkedQueue
- 自定义线程池
- 本文涉及的源码
正文开始
Java线程池的原理
- 线程池的设计原理类似于叫餐排队,首先餐厅有10个座位(CorePoolSize),来的人直接坐,后续来的人进行排队(WorkQueue),人来的再多的时候,餐厅立马增派人手,扩大到20个座位(MaxPoolsize),如果继续来人,那么剩下的人会被执行拒绝策略。
- 线程池参数主要包括:CorePoolSize、WorkQueue、MaxPoolsize
- 三者关系:当任务来的时候,首先核心线程数递增,然后后备的任务队列(阻塞队列)来装载,最后新增线程数至最大线程数,再多的话,就执行拒绝策略,结束的时候,大于corePoolSize的线程会根据KeepAliveTime参数来被回收。
- KeepAliveTime:配合时间单位来使用,线程池会将超过KeepAliveTime,且无事可做的线程回收。
- 线程工厂:用于创建线程,设置优先级,置于同一个线程组等。
Java线程池(ThreadPool)
- FixedThreadPool
- 固定线程数的线程池,即CorePoolSize == MaxPoolsize,
- 拒绝策略是AbortPolicy
- CachedThreadPool
- 核心线程数为0,最大线程数为Integer.MAX_VALUE。
- ScheduleThreadPool:主要包括三种方法
- schedule:定时执行
- scheduleAtFixedRate:定时执行后,按照固定的时间间隔进行再次执行
- 【注意】:
- 1、在main中不可以写service.shutdown(),否则执行不了,被关闭了
- 2、如果任务执行时间大于间隔时间,那么按照执行时间来,比如执行需要10S,间隔定时5S,间隔时间到,任务还没有执行完,那么继续等待到任务结束后,再次执行该任务。相当于单线程循环在执行。
- 【注意】:
- scheduleWithFixedDelay:定时执行,在执行结束后,间隔固定时间再次执行,具体见源码:ScheduleThreadPool_Demo。
- SingleThreadExecutor
- 仅有一个线程来执行任务,因此不会有线程安全问题
- 如果线程在执行任务的时候,出现异常,会新建线程来继续执行。
public class SingleThreadExecutor_Demo {
private static int count = 0;
private static Runnable forsing = () -> {
count++;
//出现报错,但是继续执行
if (count == 5) int y = count / 0;
System.out.println("main中线程的名字:" + Thread.currentThread().getName() + "count:" + count);
};
public static void main(String[] args) {
ExecutorService service = Executors.newSingleThreadExecutor();
for (int i = 0; i < 500; i++) service.execute(forsing);
service.shutdown();
}
}
-
SingleThreadScheduledExecutor
-
ForkJoinPool
拒绝策略
- AbortPolicy
- 对外抛出异常,由业务决定如何处理。
- DiscardPolicy
- 新任务来的时候悄无声息的直接丢弃,会造成数据丢失。
- DiscardOldestPolicy
- 悄无声息的直接丢弃最老的一个任务,会造成数据丢失。
- CallerRunsPolicy
- 交给提交任务的线程执行。
阻塞队列(WorkQueue)
- LinkedBlockingQueue
- 无界阻塞队列
- ArrayBlockingQueue
- 有界阻塞队列
- SynchronousQueue
- 同步队列,立即交付,队列长度为0
- ConcurrentLinkedQueue
- 其实是非阻塞队列
- 无界队列
自定义线程池
- 选择合适的线程池进行自定义
public static ExecutorService get(int corePoolSize){
return new ThreadPoolExecutor(
corePoolSize,
20,
60L,
TimeUnit.SECONDS,
new LinkedBlockingDeque<>());
}
参考博客:java常用的几种线程池比较