常用線程池
1、newSingleThreadExecutor
創建一個單線程化的線程池,它只會用唯一的工作線程來執行任務,保證所有任務按照指定順序(FIFO, LIFO, 優先級)執行。
public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>())); }
2、newFixedThreadPool
創建一個定長線程池,可控制線程最大并發數,超出的線程會在隊列中等待。
public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); }
3、newCachedThreadPool
創建一個可緩存線程池,如果線程池長度超過處理需要,可靈活回收空閑線程,若無可回收,則新建線程。
public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()); }
4、newScheduledThreadPool
創建一個定長線程池,支持定時及周期性任務執行。
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) { return new ScheduledThreadPoolExecutor(corePoolSize); }
Executors各個方法的弊端
newFixedThreadPool、newSingleThreadExecutor:
主要問題是堆積的請求處理隊列可能會耗費非常大的內存,甚至OOM。
newCachedThreadPool、newScheduledThreadPool:
主要問題是線程數最大數是Integer.MAX_VALUE,可能會創建數量非常多的線程,甚至OOM。
線程池的作用
1、提高效率 創建好一定數量的線程放在池中,等需要使用的時候就從池中拿一個,這要比需要的時候創建一個線程對象要快的多。
2、方便管理 可以編寫線程池管理代碼對池中的線程同一進行管理,比如說啟動時有該程序創建100個線程,每當有請求的時候,就分配一個線程去工作,如果剛好并發有101個請求,那多出的這一個請求可以排隊等候,避免因無休止的創建線程導致系統崩潰。