一、常见的五中线程池
【1】Executors.newFixedThreadPool(n):创建一个定长的线程池,可控制线程最大并发数,超出的线程会在队列中等待。创建的线程池 corePoolSize 和 maximumPoolSize 值是相等的,使用的是 LinkedBlockingQueue 阻塞队列。执行长期的任务,性能好很多。底层实现如下:
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
【2】Executors.newSingleThreadExecutor():创建一个单线程的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序执行。将 corePoolSize 和 maximumPoolSize 都设置为1,使用的是 LinkedBlockingQueue 阻塞队列。适合一个任务一个任务执行的场景。底层实现如下:
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService(new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
【3】Executors.newCachedThreadPool():创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收线程,则新建线程。
将 corePoolSize 设置为0,maximumPoolSize 设置为Integer.MAX_VALUE ,使用的阻塞队列是SynchronousQueue,也就是说来了任务就创建线程运行,当线程空闲超过60秒,就销毁线程。适合执行很多短期异步的小程序或者负载较轻的服务器。
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
【4】Executors.newScheduledThreadPool(n):了解
【5】Executors.newWorkStealingPool():了解
阿里巴巴开发手册:
①、线程资源必须通过线程池提供,不允许在应用中自行显示创建。因为使用线程池能够减少在创建和销毁线程上所消耗的时间以及系统开销,解决资源不足问题。如果不适用线程池,有可能造成系统创建大量同类线程而导致消耗完内存或“过度切换”的问题。
②、线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式创建,这样的方式让写的同学更加明确线程池的运行的规则,避免资源耗尽的风险。例如上述前两个使用的阻塞队列是 LinkedBlockingQueue 该阻塞队列虽有界但也相当于无界,因为其长度为 Integer.MAX_VALUE 将近2亿多,可能堆积大量的请求,从而导致 OOM 。也就是说实际生产中,不使用上述的 Executors 工具类来创建线程池。
网友评论