如同數據庫鏈接同樣,線程的建立、切換和銷燬一樣會耗費大量的系統資源。爲了複用建立好的線程,減小頻繁建立線程的次數,提升線程利用率能夠引用線程池技術。使用線程池的優點有以下幾點:
一、保持必定數量的線程,減小了線程頻繁建立和銷燬資源消耗。
二、使用線程的時候直接由線程池中取出線程,省去了建立線程的時間,側面提升了系統的響應時間。
三、須要使用線程的時候直接從線程池中取出,避免了人爲的不合理建立線程,減小了潛在的風險。
Doug Lea在實現JUC中提供了原生的線程池,並提供了各類線程管理策略來適應於不一樣的使用場景。使用的時候可經過Executors獲取各類線程池實例。html
這裏提供了六對12個方法來建立ExecutorService,其中每種類型的ExecutorService能夠適用於不一樣的應用場景,對線程的管理策略也各不相同。下面就看一下各個方法的註釋:java
/** * Creates a thread pool that creates new threads as needed, but will reuse previously constructed threads when they are available. * 建立一個線程池,須要的時候會建立新的線程,若是有可用的線程則會複用之前已經建立好的線程。 * These pools will typically improve the performance of programs that execute many short-lived asynchronous tasks. * 這些線程池一般狀況下能夠提高哪些短時間異步任務的性能 * Calls to {@code execute} will reuse previously constructed threads if available. * 若是以建立的線程狀態可用的話,調用execute能夠複用他們 * If no existing thread is available, a new thread will be created and added to the pool. * 若是不存在可用狀態的線程,那麼將會建立一個新線程同時會把該線程添加到線程池中 * Threads that have not been used for sixty seconds are terminated and removed from the cache. *那些超過60s沒用的線程將會被銷燬同時從緩存中移除 * Thus, a pool that remains idle for long enough will not consume any resources. *所以長時間空閒的線程池不會消耗任何資源 * Note that pools with similar properties but different details (for example, timeout parameters) may be created using {@link ThreadPoolExecutor} constructors. *可使用ThreadPoolExecutor建立性質類似但實現細節不一樣的線程池 * @return the newly created thread pool */ public static ExecutorService newCachedThreadPool(); //可使用自定義的ThreadFactory 類建立線程,其它和無參方法一致 public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory);
/** * Creates a thread pool that reuses a fixed number of threads operating off a shared unbounded queue. *建立一個可重用、固定數量線程的線程池 * At any point, at most {@code nThreads} threads will be active processing tasks. *任什麼時候間最多隻有 nThreads 個線程被激活來執行任務 * If additional tasks are submitted when all threads are active, they will wait in the queue until a thread is available. * 當無可用空閒線程的時候,若是有新任務被提交,這些新任務將會一直等待直至有可用線程來執行。 * If any thread terminates due to a failure during execution prior to shutdown, a new one will take its place if needed to execute subsequent tasks. *若是任何線程正常關閉以前在執行過程當中因失敗而提早終止,那麼若是有未被執行的後續任務,則會建立新的線程來繼續執行。 * The threads in the pool will exist until it is explicitly {@link ExecutorService#shutdown shutdown}. * 線程池中的全部線程在明確掉用shutdown以後將會退出 * * @param nThreads the number of threads in the pool * @return the newly created thread pool * @throws IllegalArgumentException if {@code nThreads <= 0} */ public static ExecutorService newFixedThreadPool(int nThreads); //可自定義ThreadFactory public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory);
/** * Creates a thread pool that can schedule commands to run after a given delay, or to execute periodically. * 建立一個線程池,該線程在延遲指定時間以後能夠週期性的執行線程體 * @param corePoolSize the number of threads to keep in the pool, * even if they are idle * @return a newly created scheduled thread pool 注意返回值類型是ScheduledExecutorService,不要使用ExecutorService來接收,不然找不到schedule執行方法 * @throws IllegalArgumentException if {@code corePoolSize < 0} */ public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize); //可自定義ThreadFactory public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize, ThreadFactory threadFactory);
/** * Creates an Executor that uses a single worker thread operating off an unbounded queue. *建立一個Executor,使用一個線程來工做,該線程存儲在LinkedBlockingQueue中 * (Note however that if this single thread terminates due to a failure during execution prior to shutdown, a new one will take its place if needed to execute subsequent tasks.) *注,若是任何線程正常關閉以前在執行過程當中因失敗而提早終止,那麼若是有未被執行的後續任務,則會建立新的線程來繼續執行。 * Tasks are guaranteed to execute sequentially, and no more than one task will be active at any given time. * 任務是按順序執行的,任什麼時候間都只有一個線程來執行任務 * Unlike the otherwise equivalent {@code newFixedThreadPool(1)} the returned executor is guaranteed not to be reconfigurable to use additional threads. * * @return the newly created single-threaded Executor */ public static ExecutorService newSingleThreadExecutor(); //可自定義ThreadFactory public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory);
/** * Creates a single-threaded executor that can schedule commands * to run after a given delay, or to execute periodically. * (Note however that if this single * thread terminates due to a failure during execution prior to * shutdown, a new one will take its place if needed to execute * subsequent tasks.) Tasks are guaranteed to execute * sequentially, and no more than one task will be active at any * given time. Unlike the otherwise equivalent * {@code newScheduledThreadPool(1)} the returned executor is * guaranteed not to be reconfigurable to use additional threads. * @return the newly created scheduled executor */ public static ScheduledExecutorService newSingleThreadScheduledExecutor(); public static ScheduledExecutorService newSingleThreadScheduledExecutor(ThreadFactory threadFactory)
使用示例:數據庫
package thread.blogs.threadpool; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; /** * Created by PerkinsZhu on 2017/8/31 13:59. */ public class PoolTest { public static void main(String[] args) { // testCachedThreadPool(); // testSingleThreadExecutor(); // testFixedThreadPool(); testScheduledThreadPool(); } private static ThreadFactory myFactory = new MyThreadFactory(); private static void testSingleThreadExecutor() { //一個一個的依次執行 doHandle(Executors.newSingleThreadExecutor(myFactory)); } private static void testFixedThreadPool() { //兩個兩個的一塊兒執行 doHandle(Executors.newFixedThreadPool(2,myFactory)); } private static void testCachedThreadPool() { //10個一塊兒一次性執行完 doHandle(Executors.newCachedThreadPool(myFactory)); } private static void testScheduledThreadPool() { //定時週期執行 Executors.newScheduledThreadPool(1,myFactory).scheduleAtFixedRate(runnable, 500, 2000, TimeUnit.MILLISECONDS); } private static Runnable runnable = () -> { sleep(1000); System.out.println(Thread.currentThread().getName() + " work!!!"); }; private static void doHandle(ExecutorService executorService) { for (int i = 0; i < 10; i++) { executorService.execute(runnable); } executorService.shutdown(); } private static void sleep(int time) { try { Thread.sleep(time); } catch (InterruptedException e) { e.printStackTrace(); } } } class MyThreadFactory implements ThreadFactory {//自定義ThreadFactory private static final AtomicInteger poolNumber = new AtomicInteger(1); private final ThreadGroup group; private final AtomicInteger threadNumber = new AtomicInteger(1); private final String namePrefix; MyThreadFactory() { SecurityManager s = System.getSecurityManager(); group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup(); namePrefix = "☆☆☆--" + poolNumber.getAndIncrement() + "-****-"; } public Thread newThread(Runnable r) { Thread t = new Thread(group, r, namePrefix + threadNumber.getAndIncrement(), 0); if (t.isDaemon()) { t.setDaemon(false); } if (t.getPriority() != Thread.NORM_PRIORITY) { t.setPriority(Thread.NORM_PRIORITY); } return t; } }
在使用的時候必須明白各類線程池是否適用於本身的情景,選取合適的線程池進行使用。緩存
=========================================多線程
原文連接:多線程(七)JDK原生線程池轉載請註明出處!異步
=========================================async
---endpost