日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

Java 使用線程池執行多個任務的示例

瀏覽:23日期:2022-08-15 17:51:56

在執行一系列帶有IO操作(例如下載文件),且互不相關的異步任務時,采用多線程可以很極大的提高運行效率。線程池包含了一系列的線程,并且可以管理這些線程。例如:創建線程,銷毀線程等。本文將介紹如何使用Java中的線程池執行任務。

1 任務類型

在使用線程池執行任務之前,我們弄清楚什么任務可以被線程池調用。按照任務是否有返回值可以將任務分為兩種,分別是實現Runnable的任務類(無參數無返回值)和實現Callable接口的任務類(無參數有返回值)。在打代碼時根據需求選擇對應的任務類型。

1.1 實現Runnable接口的類

多線程任務類型,首先自然想到的就是實現 Runnable 接口的類,Runnable接口提供了一個抽象方法run,這個方法無參數,無返回值。例如:

Runnable task = new Runnable() { @Override public void run() { System.out.println('Execute task.'); }};

或者Java 8 及以上版本更簡單的寫法:

Runnable task = ()->{ System.out.println('Execute task.');};1.2 實現Callable接口的類

于Runnable一樣Callable也只有一個抽象方法,不過該抽象方法有返回值。在實現該接口的時候需要制定返回值的類型。例如:

Callable<String> callableTask = ()-> 'finished';2 線程池類型

java.util.concurrent.Executors 提供了一系列靜態方法來創建各種線程池。下面例舉出了主要的一些線程池及特性,其它未例舉線程池的特性可由下面這些推導出來。

2.1 線程數固定的線程池 Fixed Thread Pool

顧名思義,這種類型線程池線程數量是固定的。如果線程數量設置為n,則任何時刻該線程池最多只有n個線程處于運行狀態。當線程池中處于飽和運行狀態時,再往線程池中提交的任務會被放到執行隊列中。如果線程池處于不飽和狀態,線程池也會一直存在,直到ExecuteService 的shutdown方法被調用,線程池才會被清除。

// 創建線程數量為5的線程池。ExecutorService executorService = Executors.newFixedThreadPool(5);2.2 可緩存的線程池 Cached Thread Pool

這種類型的線程池初始大小為0個線程,隨著往池里不斷提交任務,如果線程池里面沒有閑置線程(0個線程也表示沒有閑置線程),則會創建新的線程,保證沒有任務在等待;如果有閑置線程,則復用閑置狀態線程執行任務。處于閑置狀態的線程只會在線程池中緩存60秒,閑置時間達到60s的線程會被關閉并移出線程池。在處理大量短暫的(官方說法:short-lived)異步任務時可以顯著得提供程序性能。

//創建一個可緩存的線程池 ExecutorService executorService = Executors.newCachedThreadPool();2.3 單線程池

這或許不能叫線程池了,由于它里面的線程永遠只有1個,而且自始至終都只有1個(為什么說這句話,因為要和 Executors.newFixedThreadPool(1) 區別開來),所以還是叫它“單線程池把”。你盡可以往單線程池中添加任務,但是每次只執行1個,且任務是按順序執行的。如果前面的任務出現了異常,當前線程會被銷毀,但1個新的線程會被創建用來執行后面的任務。以上這些和線程數只有1個的線程Fixed Thread Pool一樣。兩者唯一不同的是, Executors.newFixedThreadPool(1) 可以在運行時修改它里面的線程數,而 Executors.newSingleThreadExecutor() 永遠只能有1個線程。

//創建一個單線程池ExecutorService executorService = Executors.newSingleThreadExecutor();2.4 工作竊取線程池

扒開源碼,會發現工作竊取線程池本質是 ForkJoinPool ,這類線程池充分利用CPU多核處理任務,適合處理消耗CPU資源多的任務。它的線程數不固定,維護的任務隊列有多個,當一個任務隊列完成時,相應的線程會從其它的任務隊列中竊取任務執行,這也意味著任務的開始執行順序并和提交順序相同。如果有更高的需求,可以直接通過ForkJoinPool獲取線程池。

//創建一個工作竊取線程池,使用CPU核數等于機器的CPU核數ExecutorService executorService = Executors.newWorkStealingPool();//創建一個工作竊取線程池,使用CPU 3 個核進行計算,工作竊取線程池不能設置線程數ExecutorService executorService2 = Executors.newWorkStealingPool(3);2.5 計劃任務線程池

計劃任務線程池可以按計劃執行某些任務,例如:周期性的執行某項任務。

// 獲取一個大小為2的計劃任務線程池ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(2);// 添加一個打印當前線程信息計劃任務,該任務在3秒后執行scheduledExecutorService.schedule(() -> { System.out.println(Thread.currentThread()); }, 3, TimeUnit.SECONDS);// 添加一個打印當前線程信息計劃任務,該任務在2秒后首次執行,之后每5秒執行一次。如果任務執行時間超過了5秒,則下一次將會在前一次執行完成之后立即執行scheduledExecutorService.scheduleAtFixedRate(() -> { System.out.println(Thread.currentThread()); }, 2, 5, TimeUnit.SECONDS);// 添加一個打印當前線程信息計劃任務,該任務在2秒后首次執行,之后每次在任務執行之后5秒執行下一次。scheduledExecutorService.scheduleWithFixedDelay(() -> { System.out.println(Thread.currentThread()); }, 2, 5, TimeUnit.SECONDS);// 逐個清除 idle 狀態的線程scheduledExecutorService.shutdown();// 阻塞,在線程池被關調之前代碼不再往下走scheduledExecutorService.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS);3 使用線程池執行任務

前面提到,任務類型分為有返回值和無返回值的類型,這里的調用也分為有返回值調用和無返回值的調用。

3.1 無返回值任務的調用

如果是無返回值任務的調用,可以用execute或者submit方法,這種情況下二者本質上一樣。為了于有返回值任務調用保持統一,建議采用submit方法。

//創建一個線程池ExecutorService executorService = Executors.newFixedThreadPool(3);//提交一個無返回值的任務(實現了Runnable接口)executorService.submit(()->System.out.println('Hello'));executorService.shutdown();executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS);

如果有一個任務集合,可以一個個提交。

//創建一個線程池ExecutorService executorService = Executors.newFixedThreadPool(3);List<Runnable> tasks = Arrays.asList( ()->System.out.println('Hello'), ()->System.out.println('World'));//逐個提交任務tasks.forEach(executorService::submit);executorService.shutdown();executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS);3.2 有返回值任務的調用

有返回值的任務需要實現Callable接口,實現的時候在泛型位置指定返回值類型。在調用submit方法時會返回一個Future對象,通過Future的方法get()可以拿到返回值。這里需要注意的是,調用get()時代碼會阻塞,直到任務完成,有返回值。

ExecutorService executorService = Executors.newFixedThreadPool(2);Future<String> future = executorService.submit(()->'Hello');System.out.println(future.isDone());//falseString value = future.get();System.out.println(future.isDone());//trueSystem.out.println(value);//Hello

如果要提交一批任務,ExecutorService除了可以逐個提交之外,還可以調用invokeAll一次性提交,invokeAll的內部實現其實就是用一個循環逐個提交任務。invokeAll返回的值是一個Future List。

ExecutorService executorService = Executors.newFixedThreadPool(2);List<Callable<String>> tasks = Arrays.asList(()->'Hello', ()->'World');List<Future<String>> futures = executorService.invokeAll(tasks);

invokeAny方法也很有用,線程池執行若干個實現了Callable的任務,然后返回最先執行結束的任務的值,其它未完成的任務將被正常取消掉不會有異常。如下代碼不會輸出“Hello”

ExecutorService executorService = Executors.newFixedThreadPool(2);List<Callable<String>> tasks = Arrays.asList( () -> { Thread.sleep(500L); System.out.println('Hello'); return 'Hello'; }, () -> { System.out.println('World'); return 'World'; });String s = executorService.invokeAny(tasks);System.out.println(s);//World

輸出:

WorldWorld

另外,在查看ExecutorService源碼時發現它還提供了一個方法 <T> Future<T> submit(Runnable task, T result); ,可以通過這個方法提交一個實現了Runnable接口的任務,然后有返回值,而Runnable接口中的run方法時沒有返回值的。那它的返回值是哪來的呢?其實問題在于該submit方法后面的一個參數,這個參數值就是返回的值。調用submit方法之后,有一通操作,然后直接把result參數返回了。

ExecutorService executorService = Executors.newFixedThreadPool(1);Future<String> future = executorService.submit(() -> System.out.println('Hello'), 'World');System.out.println(future.get());//輸出:World4 小結

在利用多線程處理任務時,應該根據情況選擇合適的任務類型和線程池類型。如果無返回值,可以采用實現Runnable或Callable接口的任務;如果有返回值,應該使用實現Callable接口的任務,返回值通過Future的get方法取到。選用線程池時,如果只用1個線程,用單線程池或者容量為1的固定容量線程池;處理大量short-live任務是,使用可緩存的線程池;若要有計劃或者循環執行某些任務,可以采用計劃任務線程池;如果任務需要消耗大量的CPU資源,應用工作竊取線程池。

以上就是Java 使用線程池執行多個任務的示例的詳細內容,更多關于Java 線程池執行任務的資料請關注好吧啦網其它相關文章!

標簽: Java
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
zzzwww在线看片免费| 亚洲大全视频| 日韩中出av| 午夜久久av | 伊人久久婷婷| 欧美日韩中文字幕一区二区三区| 日韩视频网站在线观看| 日韩欧美一区二区三区免费看| 激情不卡一区二区三区视频在线| 免费在线亚洲欧美| 国产精品一区高清| 国产一区二区三区四区五区传媒 | 国产伦精品一区二区三区视频 | 久久精品国产精品亚洲毛片| 精品一区二区三区免费看 | 日韩av首页| 欧洲在线一区| 合欧美一区二区三区| 国产毛片久久| 日韩精品三区四区| 免费在线日韩av| 久久精品亚洲人成影院 | 国产精品一页| 国产va在线视频| 欧美99久久| 亚洲精品日韩久久| 久久精品99国产国产精| 精品99久久| 亚洲激情偷拍| 青青国产精品| 国产美女高潮在线| 99成人在线| 欧美一区免费| av在线最新| 久久一二三区| 捆绑调教美女网站视频一区| 久久久久久久久99精品大| 亚洲欧美日韩国产一区二区| 国产一区 二区| 中文字幕在线看片| 免费视频一区二区| 国产欧美亚洲一区| 日韩在线观看一区| 久久性天堂网| 国产一区二区三区日韩精品| 久久精品播放| 午夜精品影视国产一区在线麻豆| 欧美精品不卡| 在线精品视频在线观看高清| 91嫩草精品| 日韩欧美少妇| 欧美一区二区三区久久| 欧美天堂视频| 中文字幕中文字幕精品| 精品伊人久久久| 免费日韩一区二区| 欧美aaaaaa午夜精品| 99久久久久| 久久国产生活片100| 久久久国产亚洲精品| 日韩精品成人在线观看| 欧洲av不卡| 日韩不卡免费视频| 亚洲午夜一级| 久久中文字幕一区二区| 久久成人亚洲| 欧美日韩国产观看视频| 涩涩涩久久久成人精品| 国产福利电影在线播放| 日韩一区二区三区精品视频第3页 日韩一区二区三区免费视频 | 午夜国产精品视频免费体验区| 久久精品99久久久| 国产农村妇女精品一二区| 精品视频亚洲| 色综合视频一区二区三区日韩 | 黄色日韩精品| 日本久久综合| 日本国产亚洲| 99国内精品| 麻豆mv在线观看| 久久国产尿小便嘘嘘| 国产视频一区在线观看一区免费| 精品久久精品| 亚洲视频国产| 日韩不卡免费高清视频| 国产精久久久| 日韩高清不卡在线| 国产午夜精品一区二区三区欧美| 国产精品麻豆久久| 国产精品视频3p| 亚洲精品伊人| 欧美专区在线| 国产一区清纯| 亚洲国产福利| 国产精品久av福利在线观看| 丝袜a∨在线一区二区三区不卡 | 黄色国产精品| 成人羞羞视频在线看网址| 久久久久黄色| 视频国产精品| 免费在线观看成人| 欧美日韩国产高清| 美女一区网站| 麻豆精品在线视频| 久久国内精品| 日韩黄色av| 日韩手机在线| 蜜臀久久99精品久久久画质超高清 | 国产精品视频一区二区三区综合 | 偷拍亚洲精品| 视频在线观看国产精品| 九九在线精品| 久久国产欧美| 欧美aⅴ一区二区三区视频| 涩涩涩久久久成人精品| 视频一区二区三区中文字幕| 视频小说一区二区| 中文字幕高清在线播放| 精品国产美女a久久9999| 青青伊人久久| 爽好多水快深点欧美视频| 国产婷婷精品| 亚洲永久字幕| 日韩午夜精品| 亚洲激情社区| 亚洲深夜福利| 男女男精品网站| 亚洲精品免费观看| 亚洲香蕉视频| 蜜桃久久精品一区二区| 久久最新视频| 亚洲精品观看| 日韩国产在线一| 午夜天堂精品久久久久| 蜜桃一区二区三区在线观看| av成人国产| 鲁大师成人一区二区三区| 久色成人在线| 亚洲精品护士| 天堂俺去俺来也www久久婷婷| 亚洲人成网77777色在线播放| 亚洲三区欧美一区国产二区| 男女激情视频一区| 亚洲ww精品| 婷婷综合福利| 国产精品xxx| 日本在线啊啊| 久久国产电影| 99xxxx成人网| 最新亚洲国产| 国产美女精品视频免费播放软件| 久久99偷拍| 91精品韩国| 国产模特精品视频久久久久| 亚洲免费资源| 国产精品一区二区精品视频观看 | 日韩国产在线观看一区| 国产精品久久久一区二区| 精品高清久久| 亚洲一级特黄| 视频一区中文字幕国产| 日韩欧美中文字幕电影| 欧美a在线观看| 日韩成人亚洲| 亚洲一区国产| 亚洲色图国产| 欧美精品1区| 日韩中文首页| 香蕉久久夜色精品国产| 日本视频在线一区| 91视频精品| 99视频一区| 日韩av午夜在线观看| 成人在线超碰| 亚洲婷婷免费| 日韩av午夜在线观看| 精品视频91| 午夜国产精品视频| 国产精品调教视频| 欧美影院三区| 另类av一区二区| 久久99精品久久久野外观看| 久久精品高清| 日本中文字幕视频一区| 国产99在线| 日韩在线观看中文字幕| 国产99在线| 久久午夜精品| 丰满少妇一区| 久久午夜精品一区二区| 久久香蕉精品香蕉| 国产精品普通话对白| 国产精品a久久久久| 欧美日韩激情| 国产剧情一区二区在线观看| sm久久捆绑调教精品一区| 亚洲人亚洲人色久| 成人精品亚洲| 国产欧美欧美| 日韩视频中文|