日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

(转)java并发之Executor

發布時間:2024/8/26 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 (转)java并发之Executor 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

場景: 線程池在面試時候經常會碰到,在工作中用的場景更多,所以很有必要弄清楚。

1 簡介

Java自1.5以來加入了處理一批線程的方法,也就是java并發包里的Executor。本文主要介紹ExecutorService的用法,Runable和Callable的用法以及ExecutorCompletionService的用法。?
使用Executor來執行多個線程的好處是用來避免線程的創建和銷毀的開銷,以提升效率。

因此如果某些場景需要反復創建線程去處理同類事務的話,可以考慮使用線程池來處理。
其實Executor本身并不實現純種池的功能,只是提供了獲取ExecutorService的方法,而ExecutorService才是真正處理線程池相關邏輯的類。

Executor下獲取ExecutorService 的方法有很多,用于獲取各種不同的純種池,如單線程線程池、固定線程數的線程池等,不過最終還是調用ExecutorService的構造函數來創建,如下:

public ThreadPoolExecutor(int corePoolSize,//最少線程數int maximumPoolSize,//最大線程數long keepAliveTime,//線程池滿后,后續線程的等待時間TimeUnit unit,//等待時間的單位BlockingQueue<Runnable> workQueue,//等待線程隊列ThreadFactory threadFactory)//線程生產工廠

1.1 ?Runable

通過以上方法就可以創建一個線程池方法,可以限制線程的數量和等待隊列中線程的等待時間等。然后如果要通過這個線程池來執行線程:

executorService.execute(new Runnable() {@Overridepublic void run() {System.out.println("Execute in pool:" + Thread.currentThread().getId());} });

通過execute()方法的執行是異步的,無法知道線程什么時候執行完畢

?

如果要想知道線程是否執行完畢,可以通過另外一個方法submit()來執行,然后獲取到一個future對象, 然后通過get()方法來判斷是否執行完畢:

Future<?> future = executorService.submit(new Runnable() {@Overridepublic void run() {try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("Execute in pool:" + Thread.currentThread().getId());} }); try {if(future.get()==null){System.out.println("finish!!!");} } catch (InterruptedException e) {e.printStackTrace(); } catch (ExecutionException e) {e.printStackTrace(); }

但是通過這種方式只能知道線程是否執行完畢,卻做不到將各線程的處理結果返回做歸并處理

要實現這個目的可以使用Callable接口來封裝任務邏輯,Callable和Runable的 唯一區別就是它支持返回處理結果:

1.2?Callable

可以處理線程執行完之后的返回結果

Future<?> future = executorService.submit(new Callable<String>() {@Overridepublic String call() throws Exception {return "hello callable!";}}); try {System.out.println(future.get()); } catch (InterruptedException e) {e.printStackTrace(); } catch (ExecutionException e) {e.printStackTrace(); }

其中call()方法中返回的值,就是Future對象get()到的值。但是如果有多個線程在處理,然后要將這些線程的處理結果歸并怎么做呢?

當然可以使用ExecutorService來獲取每個放到線程池的線程的Future對象,然后遍歷的去get()然后去做歸并處理。但是顯然這種方法并不能做到先完成的就被先歸并,而是取決于遍歷到的時間,這顯然降低了處理效率。

要處理這種場景,可以使用另外一個Service–ExecutorCompletionService:

1.3?ExecutorCompletionService

package test03;import java.util.concurrent.Callable; import java.util.concurrent.CompletionService; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorCompletionService; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors;import org.junit.Test;public class ExecutorCompletionServiceTest {@Testpublic void test() {ExecutorService executorService = Executors.newFixedThreadPool(4);CompletionService<Long> completionService = new ExecutorCompletionService<Long>(executorService);for (int i = 0; i < 4; i++) {long sleep = (5 - i) * 1000;completionService.submit(new ExeWorker(sleep)); //使用CompletionService來調用線程,可以做到先完成先處理 }for(int i=0;i<4;i++){try {System.out.println(completionService.take().get()+" Get!"); //獲取線程處理后的返回結果} catch (InterruptedException e) {e.printStackTrace();} catch (ExecutionException e) {e.printStackTrace();}}}}class ExeWorker implements Callable<Long> {private long sleep;public ExeWorker(long sleep) {this.sleep = sleep;}@Overridepublic Long call() throws Exception {System.out.println(sleep + " Executing!");Thread.sleep(sleep);System.out.println(sleep + " Done!");return sleep;}}

?

以線程的sleep時間為線程名稱,然后輸出結果為:

可以看出后面那個循環獲取處理結果的地方的確是按先完成先返回的方式來實現。這種方法的一個約束就是需要知道有多少個線程在處理(不是很理解)

其實CompletionService底層是通過一個BlockingQueue來存放處理結果,你也可以使用它自身封裝好的帶超時的poll方法來獲取返回結果。

?

轉載于:https://www.cnblogs.com/lixuwu/p/6067723.html

總結

以上是生活随笔為你收集整理的(转)java并发之Executor的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。