线程池的作用
- 限制系统中执行线程的数量,防止不断开辟新线程而造成的资源枯竭;
- 线程池维护着一个线程的集合,在需要执行新的任务时重用这些线程而不是新建一个线程(提高线程复用,减少性能开销)。
如何创建线程池

参数解释:
- corePoolSize:核心池大小,即在没有任务执行时线程池的大小,并且只有在工作队列满了的情况下才会创建超出这个数量的线程(但小于最大池大小)。
- maximumPoolSize:最大池大小,可同时活动的线程数的上限,若空闲时,会销毁超出核心池大小的多余线程。
- keepAliveTime:空闲线程超时时间,若一个线程已经闲置的时间超过了存活时间,它将成为一个被回收的候选者,若当前的池大小已经超过了核心池大小,这个线程会被终止掉。
- BlockingQueue:任务阻塞队列,当所有的核心线程都在干活时,新添加的任务会被添加到这个队列中等待处理,如果队列满了,则新建非核心线程执行任务。有如下几种:
1.无限队列:newFixedThreadPool和newSingleThreadExecutor默认使用一个无限的LinkedBlockingQueue阻塞队列,若所有工作者线程都处于忙碌,任务将会在队列中等候,若任务持续快速地到达,队列也会无限制地增加。
2.有限队列:为了避免资源被耗尽,线程池也经常使用有限队列,如ArrayBlockingQueue或有界的LinkedBlockingQueue;当队列满时,新来的任务会使用饱和策略处理。
3.同步移交:同步移交适合线程池无限或者可以接受任务被拒绝的情况,newCachedThreadPool就使用同步移交方式。使用SychronousQueue来避免任务排队,他不是一个真正的队列,可以将任务从生产者移交给工作者。
- ThreadFactory:线程工厂。
- RejectedExecutionHandler:拒绝策略,有如下几种:
1.中止(abort):默认的饱和策略,会抛出未检查的拒绝执行异常RejectedExecutionException,调用者捕获该异常做适当处理。
2.遗弃(discard):丢弃最新提交的任务。
3.遗弃最旧的(discard-oldest):丢弃本应该接下来就要执行的任务,并尝试去重新提交新任务,若是优先级队列,则丢弃优先级最高的任务,因此不能混合使用遗弃最旧的饱和策略和优先级队列。
4.调用者运行(caller-runs):既不会丢最新提交的任务,也不会抛出异常,会把最新提交的任务推回到调用者,由生产者线程执行,一方面给工作者线程时间来追赶进度,另一方面减慢了生产者提交新任务的速度。
Executors提供了四种创建好的线程池:
- newFixedThreadPool:创建一个固定长度的线程池,每当提交一个任务时就创建一个线程,直到达到线程池的最大数量,此时线程池的规模将不再变化。
public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); } - newSingleThreadExecutor:单线程线程池,能确保依照任务在队列中的顺序串行执行。
public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>())); } - newCachedThreadPool:创建一个可以无限扩张的线程池。
public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()); } - newScheduledThreadPool:创建一个固定长度的线程池,以延时或定时的方式来执行任务,类似于Timer。
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) { return new ScheduledThreadPoolExecutor(corePoolSize); }
示例
public class ThreadPoolTest {
public static void main(String[] args) {
ExecutorService threadPool1=new ThreadPoolExecutor(
5,
5,
0L,
TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>(1024));
ExecutorService threadPool2=Executors.newFixedThreadPool(5);
ExecutorService threadPool3=Executors.newCachedThreadPool();
ExecutorService threadPool4=Executors.newScheduledThreadPool(3);
ExecutorService threadPool5=Executors.newSingleThreadExecutor();
}
}
更多示例:https://blog.csdn.net/achuo/article/details/80623893
阿里规约中不建议使用Executors去创建线程池,而是通过ThreadPoolExecutor,因为它的弊端在于:
- newFixedThreadPool和newSingleThreadExecutor默认使用一个无限的LinkedBlockingQueue阻塞队列,堆积的请求处理队列可能会耗费非常大的内存,甚至OOM。
- newCachedThreadPool和newScheduledThreadPool的线程最大数是Integer.MAX_VALUE,可能会创建非常多的线程,甚至OOM。
阿里规约中给出的创建线程池的示例:
ThreadFactory namedThreadFactory=new ThreadFactoryBuilder().setNameFormat("demo-pool-%d").build();
ExecutorService threadPool6=new ThreadPoolExecutor(
5,
200,
0L,
TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>(1024), namedThreadFactory, new ThreadPoolExecutor.AbortPolicy());
其中ThreadFactoryBuilder来源于Google的guava包。
2500

被折叠的 条评论
为什么被折叠?



