四種Java線程池用法解析。本站提示廣大學習愛好者:(四種Java線程池用法解析)文章只能為提供參考,不一定能成為您想要的結果。以下是四種Java線程池用法解析正文
本文為年夜家剖析四種Java線程池用法,供年夜家參考,詳細內容以下
1、new Thread的弊病
履行一個異步義務你還只是以下new Thread嗎?
new Thread(new Runnable() { @Override public void run() { // TODO Auto-generated method stub } } ).start();
那你就out太多了,new Thread的弊病以下:
a. 每次new Thread新建對象機能差。
b. 線程缺少同一治理,能夠無窮制新建線程,互相之間競爭,及能夠占用過量體系資本招致逝世機或oom。
c. 缺少更多功效,如准時履行、按期履行、線程中止。
比擬new Thread,Java供給的四種線程池的利益在於:
a. 重用存在的線程,削減對象創立、滅亡的開支,機能佳。
b. 可有用掌握最年夜並發線程數,進步體系資本的應用率,同時防止過量資本競爭,防止梗塞。
c. 供給准時履行、按期履行、單線程、並發數掌握等功效。
2、Java 線程池
Java經由過程Executors供給四種線程池,分離為:
newCachedThreadPool創立一個可緩存線程池,假如線程池長度跨越處置須要,可靈巧收受接管余暇線程,若無可收受接管,則新建線程。
newFixedThreadPool 創立一個定長線程池,可掌握線程最年夜並發數,超越的線程會在隊列中期待。
newScheduledThreadPool 創立一個定長線程池,支撐准時及周期性義務履行。
newSingleThreadExecutor 創立一個單線程化的線程池,它只會用獨一的任務線程來履行義務,包管一切義務依照指定次序(FIFO, LIFO, 優先級)履行。
(1)newCachedThreadPool:
創立一個可緩存線程池,假如線程池長度跨越處置須要,可靈巧收受接管余暇線程,若無可收受接管,則新建線程。示例代碼以下:
ExecutorService cachedThreadPool = Executors.newCachedThreadPool(); for (int i = 0; i < 10; i++) { final int index = i; try { Thread.sleep(index * 1000); } catch (InterruptedException e) { e.printStackTrace(); } cachedThreadPool.execute(new Runnable() { @Override public void run() { System.out.println(index); } }); }
線程池為無窮年夜,當履行第二個義務時第一個義務曾經完成,會復用履行第一個義務的線程,而不消每次新建線程。
(2)newFixedThreadPool:
創立一個定長線程池,可掌握線程最年夜並發數,超越的線程會在隊列中期待。示例代碼以下:
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3); for (int i = 0; i < 10; i++) { final int index = i; fixedThreadPool.execute(new Runnable() { @Override public void run() { try { System.out.println(index); Thread.sleep(2000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }); }
由於線程池年夜小為3,每一個義務輸入index後sleep 2秒,所以每兩秒打印3個數字。
定長線程池的年夜小最好依據體系資本停止設置。如Runtime.getRuntime().availableProcessors()。可參考PreloadDataCache。
(3)newScheduledThreadPool:
創立一個定長線程池,支撐准時及周期性義務履行。延遲履行示例代碼以下:
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5); scheduledThreadPool.schedule(new Runnable() { @Override public void run() { System.out.println("delay 3 seconds"); } }, 3, TimeUnit.SECONDS);
表現延遲3秒履行。
按期履行示例代碼以下:
scheduledThreadPool.scheduleAtFixedRate(new Runnable() { @Override public void run() { System.out.println("delay 1 seconds, and excute every 3 seconds"); } }, 1, 3, TimeUnit.SECONDS);
表現延遲1秒後每3秒履行一次。
ScheduledExecutorService比Timer更平安,功效更壯大
(4)newSingleThreadExecutor:
創立一個單線程化的線程池,它只會用獨一的任務線程來履行義務,包管一切義務依照指定次序(FIFO, LIFO, 優先級)履行。示例代碼以下:
ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor(); for (int i = 0; i < 10; i++) { final int index = i; singleThreadExecutor.execute(new Runnable() { @Override public void run() { try { System.out.println(index); Thread.sleep(2000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }); }
成果順次輸入,相當於次序履行各個義務。
現行年夜多半GUI法式都是單線程的。Android中單線程可用於數據庫操作,文件操作,運用批量裝置,運用批量刪除等不合適並發但能夠IO壅塞性及影響UI線程呼應的操作。
線程池的感化:
線程池感化就是限制體系中履行線程的數目。
根 據體系的情況情形,可以主動或手動設置線程數目,到達運轉的最好後果;少了糟蹋了體系資本,多了形成體系擁堵效力不高。用線程池掌握線程數目,其他線程排 隊等待。一個義務履行終了,再從隊列的中取最後面的義務開端履行。若隊列中沒有期待過程,線程池的這一資本處於期待。當一個新義務須要運轉時,假如線程池 中有期待的任務線程,便可以開端運轉了;不然進入期待隊列。
為何要用線程池:
1.削減了創立和燒毀線程的次數,每一個任務線程都可以被反復應用,可履行多個義務。
2.可以依據體系的蒙受才能,調劑線程池中任務線線程的數量,避免由於消費過量的內存,而把辦事器累爬下(每一個線程須要年夜約1MB內存,線程開的越多,消費的內存也就越年夜,最初逝世機)。
Java外面線程池的頂級接口是Executor,然則嚴厲意義上講Executor其實不是一個線程池,而只是一個履行線程的對象。真實的線程池接口是ExecutorService。
比擬主要的幾個類:
ExecutorService: 真實的線程池接口。
ScheduledExecutorService: 能和Timer/TimerTask相似,處理那些須要義務反復履行的成績。
ThreadPoolExecutor: ExecutorService的默許完成。
ScheduledThreadPoolExecutor: 繼續ThreadPoolExecutor的ScheduledExecutorService接話柄現,周期性義務調劑的類完成。
要設置裝備擺設一個線程池是比擬龐雜的,特別是關於線程池的道理不是很清晰的情形下,很有能夠設置裝備擺設的線程池不是較優的,是以在Executors類外面供給了一些靜態工場,生成一些經常使用的線程池。
1.newSingleThreadExecutor
創立一個單線程的線程池。這個線程池只要一個線程在任務,也就是相當於單線程串行履行一切義務。假如這個獨一的線程由於異常停止,那末會有一個新的線程來替換它。此線程池包管一切義務的履行次序依照義務的提交次序履行。
2.newFixedThreadPool
創立固定年夜小的線程池。每次提交一個義務就創立一個線程,直到線程到達線程池的最年夜年夜小。線程池的年夜小一旦到達最年夜值就會堅持不變,假如某個線程由於履行異常而停止,那末線程池會彌補一個新線程。
3.newCachedThreadPool
創立一個可緩存的線程池。假如線程池的年夜小跨越了處置義務所須要的線程,
那末就會收受接管部門余暇(60秒不履行義務)的線程,當義務數增長時,此線程池又可以智能的添加新線程來處置義務。此線程池不會對線程池年夜小做限制,線程池年夜小完整依附於操作體系(或許說JVM)可以或許創立的最年夜線程年夜小。
4.newScheduledThreadPool
創立一個年夜小無窮的線程池。此線程池支撐准時和周期性履行義務的需求。
實例代碼
1、固定年夜小的線程池,newFixedThreadPool:
package app.executors; import java.util.concurrent.Executors; import java.util.concurrent.ExecutorService; /** * Java線程:線程池 * * @author xiho */ public class Test { public static void main(String[] args) { // 創立一個可重用固定線程數的線程池 ExecutorService pool = Executors.newFixedThreadPool(2); // 創立線程 Thread t1 = new MyThread(); Thread t2 = new MyThread(); Thread t3 = new MyThread(); Thread t4 = new MyThread(); Thread t5 = new MyThread(); // 將線程放入池中停止履行 pool.execute(t1); pool.execute(t2); pool.execute(t3); pool.execute(t4); pool.execute(t5); // 封閉線程池 pool.shutdown(); } } class MyThread extends Thread { @Override public void run() { System.out.println(Thread.currentThread().getName() + "正在履行。。。"); } }
輸入成果:
pool-1-thread-1正在履行。。。 pool-1-thread-3正在履行。。。 pool-1-thread-4正在履行。。。 pool-1-thread-2正在履行。。。 pool-1-thread-5正在履行。。。
轉變ExecutorService pool = Executors.newFixedThreadPool(5)中的參數:ExecutorService pool = Executors.newFixedThreadPool(2),輸入成果是:
pool-1-thread-1正在履行。。。 pool-1-thread-1正在履行。。。 pool-1-thread-2正在履行。。。 pool-1-thread-1正在履行。。。 pool-1-thread-2正在履行。。。
從以上成果可以看出,newFixedThreadPool的參數指定了可以運轉的線程的最年夜數量,跨越這個數量的線程加出來今後,不會運轉。其次,參加線程池的線程屬於托管狀況,線程的運轉不受參加次序的影響。
2、單義務線程池,newSingleThreadExecutor:
僅僅是把上述代碼中的ExecutorService pool = Executors.newFixedThreadPool(2)改成ExecutorService pool = Executors.newSingleThreadExecutor();
輸入成果:
pool-1-thread-1正在履行。。。 pool-1-thread-1正在履行。。。 pool-1-thread-1正在履行。。。 pool-1-thread-1正在履行。。。 pool-1-thread-1正在履行。。。
可以看出,每次挪用execute辦法,其實最初都是挪用了thread-1的run辦法。
3、可變尺寸的線程池,newCachedThreadPool:
與下面的相似,只是修改下pool的創立方法:ExecutorService pool = Executors.newCachedThreadPool();
輸入成果:
pool-1-thread-1正在履行。。。 pool-1-thread-2正在履行。。。 pool-1-thread-4正在履行。。。 pool-1-thread-3正在履行。。。 pool-1-thread-5正在履行。。。
這類方法的特色是:可依據須要創立新線程的線程池,然則在之前結構的線程可用時將重用它們。
4、延遲銜接池,newScheduledThreadPool:
public class TestScheduledThreadPoolExecutor { public static void main(String[] args) { ScheduledThreadPoolExecutor exec = new ScheduledThreadPoolExecutor(1); exec.scheduleAtFixedRate(new Runnable() {//每隔一段時光就觸發異常 @Override publicvoid run() { //throw new RuntimeException(); System.out.println("================"); } }, 1000, 5000, TimeUnit.MILLISECONDS); exec.scheduleAtFixedRate(new Runnable() {//每隔一段時光打印體系時光,證實二者是互不影響的 @Override publicvoid run() { System.out.println(System.nanoTime()); } }, 1000, 2000, TimeUnit.MILLISECONDS); } }
輸入成果:
================ 8384644549516 8386643829034 8388643830710 ================ 8390643851383 8392643879319 8400643939383
以上就是本文的全體內容,願望對年夜家的進修有所贊助。