版權聲明:本文爲博主原創文章,允許轉載,請標明出處。 https://blog.csdn.net/qwdafedv/article/details/84256291
前言
爲什麼要用線程池
經常創建、銷燬 線程,將是對系統資源的極大浪費。 因此,實際開發中我們將使用線程池來管理、複用 線程。 使用線程池,可以 1.降低資源消耗: 重複利用線程,減少創建和銷燬造成的消耗。 2.提升響應速度: 任務到達,不需要創建,立即執行。 3.提高可管理型: 線程是CPU調度和分派的基本單位, 如果無限制地創建,不僅會消耗系統資源,還會降低系統穩定性。 使用線程池可以統一進行 分配、調優和監控。
線程池的分類
ThreadPoolExecutor
ThreadPoolExecutor是線程池的真正實現, 他通過構造方法的一系列參數,來構成不同配置的線程池。 常用的構造方法有下面四個
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler);
- corePoolSize: 核心池的大小。 當有任務來之後,就會創建一個線程去執行任務,當線程池中的線程數目達到corePoolSize後,就會把到達的任務放到緩存隊列當中
- maximumPoolSize: 線程池最大線程數,它表示在線程池中最多能創建多少個線程;
- keepAliveTime: 表示線程沒有任務執行時最多保持多久時間會終止。
- unit: 參數keepAliveTime的時間單位,有7種取值,在TimeUnit類中有7種靜態屬性。
- workQueue:一個阻塞隊列,提交的任務將會被放到這個隊列裏。
- threadFactory:線程工廠,用來創建線程,主要是爲了給線程起名字,默認工廠的線程名字:pool-1-thread-3。
- handler:拒絕策略,當線程池裏線程被耗盡,且隊列也滿了的時候會調用。
線程池的四種創建方式
Java通過Executors(jdk1.5併發包)提供四種線程池,分別爲:
- newCachedThreadPool創建一個可緩存線程池,如果線程池長度超過處理需要,可靈活回收空閒線程,若無可回收,則新建線程。 案例演示:
- newFixedThreadPool 創建一個定長線程池,可控制線程最大併發數,超出的線程會在隊列中等待。
- newScheduledThreadPool 創建一個定長線程池,支持定時及週期性任務執行。
- newSingleThreadExecutor 創建一個單線程化的線程池,它只會用唯一的工作線程來執行任務,保證所有任務按照指定順序(FIFO, LIFO, 優先級)執行。
newCachedThreadPool
創建一個可緩存線程池,如果線程池長度超過處理需要,可靈活回收空閒線程, 若無可回收,則新建線程。
package cn.qbz.thread; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class Test111907 { public static void main(String[] args) { ExecutorService executorService = Executors.newCachedThreadPool(); for (int i = 0; i < 10; i++) { final int temp = i; executorService.execute(new Runnable() { @Override public void run() { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + " i=" + temp); } }); } } }
public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()); }
newFixedThreadPool
創建一個定長線程池,可控制線程最大併發數,超出的線程會在隊列中等待。
package cn.qbz.thread; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class Test111907 { public static void main(String[] args) { ExecutorService executorService = Executors.newFixedThreadPool(3); for (int i = 0; i < 10; i++) { final int temp = i; executorService.execute(new Runnable() { @Override public void run() { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + " i=" + temp); } }); } } }
public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); }
newScheduledThreadPool
創建一個定長線程池,支持定時及週期性任務執行。
package cn.qbz.thread; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; public class Test111907 { public static void main(String[] args) { final long begin = System.currentTimeMillis(); ExecutorService executorService = Executors.newScheduledThreadPool(3); for (int i = 0; i < 10; i++) { final int temp = i; final long time = begin; executorService.schedule(new Runnable() { @Override public void run() { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + " i=" + temp + " time=" + (System.currentTimeMillis() - time)); } }, 5, TimeUnit.SECONDS); } } }
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) { return new ScheduledThreadPoolExecutor(corePoolSize); }
public ScheduledThreadPoolExecutor(int corePoolSize) { super(corePoolSize, Integer.MAX_VALUE, 0, TimeUnit.NANOSECONDS, new DelayedWorkQueue()); }
newSingleThreadExecutor
創建一個單線程化的線程池,它只會用唯一的工作線程來執行任務, 保證所有任務按照指定順序(FIFO, LIFO, 優先級)執行。
package cn.qbz.thread; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; public class Test111907 { public static void main(String[] args) { ExecutorService executorService = Executors.newSingleThreadExecutor(); for (int i = 0; i < 10; i++) { final int temp = i; executorService.execute(new Runnable() { @Override public void run() { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + " i=" + temp); } }); } } }