多線程(五)--線程池的基本使用
一、線程池(ThreadPoolExecutor)的創建
ThreadPoolExecutor內部的構造函數只有四種
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) { this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, Executors.defaultThreadFactory(), defaultHandler); } public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize,long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory) { this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, defaultHandler); }public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler) { this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, Executors.defaultThreadFactory(), handler); } public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) { if (corePoolSize < 0 || maximumPoolSize <= 0 || maximumPoolSize < corePoolSize || keepAliveTime < 0) throw new IllegalArgumentException(); if (workQueue == null || threadFactory == null || handler == null) throw new NullPointerException(); this.corePoolSize = corePoolSize; this.maximumPoolSize = maximumPoolSize; this.workQueue = workQueue; this.keepAliveTime = unit.toNanos(keepAliveTime); this.threadFactory = threadFactory; this.handler = handler; }
關於這些每個變量名的具體含義可以在上一篇線程池的基本介紹中看到
https://www.cnblogs.com/qqwhsj/p/10642918.html
通過這四種構造函數我們可以得知:在創建線程池時必須有的參數為:CorePoolSize,maxmumPoolSize,KeepAliveTime,Unit,workQueue。且必須按照一定順序。
可以自定義加入的是threadFactory,handler。如果你不加入,線程會通過Executors工具類默認一個線程工廠,生成一個default_handler。
二、Executors類
Executor是一種強大的線程池操作類,主要還有生成默認的線程工廠以及常見的四種線程池的創建方法,該方法都會返回一個ExecutorService對象。
當然這四種創建方法本質還是使用super調用了ThreadPoolExecutor類中的構造方法,只是將構造方法中必須寫入的corePoolSize等數據使用默認值。
常見的四種線程池創建方法:
1.SingleThreadPool:單線程化線程池,在這種線程池中,只會有一個線程的存在,將所有的任務都放置於任務池,當線程執行完一個任務後,下一個任務繼續當前線程執行。
public class ExecutorsTest { static int a=10; public static void main(String[]args){ ExecutorService singlems= Executors.newSingleThreadExecutor(); for(int i=0;i<100;i++){ singlems.execute( //將每個Runnable作為一個任務執行,無需產生多個線程 new Runnable() { @Override public void run() { System.out.println(a); try { Thread.sleep(1000); }catch (InterruptedException ie){ System.out.println("程序產生中斷異常"); } } } ); } } }
2.CachedThreadPool,創建一個緩存線程池,當任務進入時線程會創建;若沒有任務,則線程會直接銷毀。當需要是會再次創建。
public class ExecutorsTest { static int a=10; public static void main(String[]args){ ExecutorService singlems= Executors.newCachedThreadPool(); for(int i=0;i<20;i++){ try{ Thread.sleep(2000); }catch(InterruptedException ie){ ie.printStackTrace(); } singlems.execute( //將每個Runnable作為一個任務執行,無需產生多個線程 new Runnable() { @Override public void run() { System.out.println(Thread.currentThread().getName()+":輸出"); } } ); } } }
運行結果為:
pool-1-thread-1:輸出 pool-1-thread-1:輸出 pool-1-thread-1:輸出 pool-1-thread-1:輸出 pool-1-thread-1:輸出 pool-1-thread-1:輸出
3.FixedThreadPool,設置固定線程數目的線程池,每有一個任務時則會創建新的線程,但最大數目必須是你設置的最大數目。當正在運行的線程數目等於你設置的最大數目後,所有人任務都會防止與任務池中等待調用:
public class ExecutorsTest { static int a=10; public static void main(String[]args){ ExecutorService singlems= Executors.newFixedThreadPool(3); for(int i=0;i<20;i++){ singlems.execute( //將每個Runnable作為一個任務執行,無需產生多個線程 new Runnable() { @Override public void run() { try{ Thread.sleep(1000); }catch(InterruptedException ie){ ie.printStackTrace(); } System.out.println(Thread.currentThread().getName()+":輸出"); } } ); } } }
執行結果為:
pool-1-thread-1:輸出 pool-1-thread-3:輸出 pool-1-thread-2:輸出 pool-1-thread-1:輸出 pool-1-thread-3:輸出 pool-1-thread-2:輸出 pool-1-thread-1:輸出 pool-1-thread-3:輸出 pool-1-thread-2:輸出 pool-1-thread-3:輸出 pool-1-thread-1:輸出 pool-1-thread-2:輸出
4.ScheduledThreadPool:支持定時或者周期性執行任務,但是返回都是ScheduledExecutorService,也需要設置核心線程數量。
下面是執行延遲三秒,每五秒鐘執行一次的代碼:
public class ExecutorsTest { static int a=10; public static void main(String[]args){ ScheduledExecutorService singlems= Executors.newScheduledThreadPool(3); for(int i=0;i<3;i++){ singlems.scheduleAtFixedRate( //將每個Runnable作為一個任務執行,無需產生多個線程 new Runnable() { @Override public void run() { try{ Thread.sleep(1000); }catch(InterruptedException ie){ ie.printStackTrace(); } System.out.println(Thread.currentThread().getName()+":輸出"); } },3, 5,TimeUnit.SECONDS); } } }
執行結果為:
pool-1-thread-2:輸出 pool-1-thread-1:輸出 pool-1-thread-3:輸出 pool-1-thread-2:輸出 pool-1-thread-1:輸出 pool-1-thread-3:輸出
多線程(五)--線程池的基本使用