使用線程池的目的:api
線程是稀缺資源,不能頻繁的建立。ide
解耦做用;線程的建立於執行徹底分開,方便維護。ui
應當將其放入一個池子中,能夠給其餘任務進行復用。spa
建立線程池的方式:線程
在 JDK 1.5 以後推出了相關的 api,常見的建立線程池方式有如下三種:code
Executors.newCachedThreadPool()
:無限線程池。orm
Executors.newFixedThreadPool(nThreads)
:建立固定大小的線程池。blog
Executors.newSingleThreadExecutor()
:建立單個線程的線程池。隊列
可是在阿里巴巴開發規約中對線程池的建立有如下幾個強制要求:資源
能夠看到規約是不容許使用Executors直接建立線程池的,而要經過ThreadPoolExecutor的方式建立
1 public static ExecutorService newCachedThreadPool() { 2 return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 3 60L, TimeUnit.SECONDS, 4 new SynchronousQueue<Runnable>()); 5 }
咱們看到這三種方式的源碼也是經過ThreadPoolExecutor的方式來建立的,接下來咱們看一下ThreadPoolExecutor的API
1 ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler)
這幾個核心參數的做用:
corePoolSize
爲線程池的基本大小。
maximumPoolSize
爲線程池最大線程大小。
keepAliveTime
和 unit
則是線程空閒後的存活時間。
workQueue
用於存聽任務的阻塞隊列。
handler
當隊列和最大線程池都滿了以後的飽和策略。
線程池大小建立的原則:
IO 密集型任務:因爲線程並非一直在運行,因此能夠儘量的多配置線程,好比 CPU 個數 * 2
CPU 密集型任務(大量複雜的運算)應當分配較少的線程,好比 CPU 個數至關的大小。
經過SpringBoot管理線程池:
1 @Configuration 2 public class TreadPoolConfig { 3 4 5 /** 6 * 消費隊列線程 7 * @return 8 */ 9 @Bean(value = "consumerQueueThreadPool") 10 public ExecutorService buildConsumerQueueThreadPool(){ 11 ThreadFactory namedThreadFactory = new ThreadFactoryBuilder() 12 .setNameFormat("consumer-queue-thread-%d").build(); 13 14 ExecutorService pool = new ThreadPoolExecutor(5, 5, 0L, TimeUnit.MILLISECONDS, 15 new ArrayBlockingQueue<Runnable>(5),namedThreadFactory,new ThreadPoolExecutor.AbortPolicy()); 16 17 return pool ; 18 } 19 20 21 22 }
使用:
1 @Resource(name = "consumerQueueThreadPool") 2 private ExecutorService consumerQueueThreadPool; 3 4 5 @Override 6 public void execute() { 7 8 //消費隊列 9 for (int i = 0; i < 5; i++) { 10 consumerQueueThreadPool.execute(new ConsumerQueueThread()); 11 } 12 13 }
其實也挺簡單,就是建立了一個線程池的 bean,在使用時直接從 Spring 中取出便可。