ExecutorService小試牛刀

2022-06-23 08:57:09 字數 3013 閱讀 2259

現在的專案中有將學生批量加入課程的需求,於是想根據這個需求測試一下executorservice的效率。假設乙個場景:現在有100門課,1500名學生,要求每15個人加入一門課程,不重複。

查詢並拼接資料:先從mysql中查詢出100門課的id,再拿出1500個學生,然後將1500個學生每15人一組,分成100組,對應100門課程,方法如下:

public list> getgroupstudent()

}for (int i=0;i<100;i++)

}return groupstudent;

}

下面這個是不使用executorsevice的插入方法,為了體現出時間差距,總共有三個邏輯比較複雜的方法,因為涉及專案結果,這裡就不貼出細則了:

public int doadd(list

> list)

}return1;}

下面這個是使用了executorservice的插入方法:

public int doaddbyexecutor(list

> list));

}}catch(exception e)finally

return1;}

首先使用executors類的靜態方法newfixedthreadpool(int size)建立了執行緒池,其大小為list.size(),其實這裡就是100,因為將學生分成了100組。然後使用executorservice的submit方法執行任務,其中傳入的是乙個runnable的例項,這裡使用了lambda表示式。必須要注意的是,submit方法一定要try,否則容易造成死鎖,並且執行完成之後一定要shutdown掉。

我這裡寫了兩個簡單的方法,測試了一下兩種插入方法的效率:

首先是普通方法:耗時2秒左右

然後是多執行緒方法:耗時33毫秒。

這個資料量其實不算很大,但是用多執行緒來跑還是能看出來耗時差距的。試想一下,如果資料量翻十倍甚至百倍萬倍的時候,效率差距就出來了。

這只是executorservice最簡單的用法。了解一下原始碼,先看最重要的submit方法,其中有三個過載:

future> submit(runnable task);

future submit(runnable task, t result);

future submit(callable task);

submit()方法可以接受runnable和callable物件,返回future物件。

再看execute方法:

void

execute

(runnable command)

;

execute是executor介面的方法,而executorservice繼承自executor。executor方法只能接受runnable物件,沒有返回值。

再來看一下executorservice的關閉。

void

shutdown

();

listshutdownnow

();

二者的區別在於,shoudown()方法在終止前允許執行以前提交的任務,而shoutdownnow()方法阻止等待任務啟動並試圖停止當前正在執行的任務。通俗一點講,shutdown()方法只是將執行緒池的狀態設定為shutdown狀態,正在執行的任務會繼續執行下去,沒有被執行的則不能在執行。而shutdownnow()方法則是將執行緒池的狀態設定為stop,正在執行的任務則被停止,沒被執行的任務則返回。舉乙個很經典的猴子(各個執行緒)吃玉公尺(任務)的例子,假如猴子們正在非常開心的吃玉公尺,突然接到shutdown指令,那麼猴子們則會把手上的玉公尺吃完,沒有拿到手裡的地上的玉公尺則不能再吃。而如果接到shutdownnow指令,這些猴子們立即停止吃玉公尺,手上的玉公尺也要放下,地上的更不能吃。(當然,假設猴子是聽話的)

一般情況下,分兩個階段來關閉executorservice。首先呼叫shutdown()方法拒絕傳入新任務。其次,如果有必要的話再呼叫shutdownnow方法取消所有遺留的任務。

上面講到了,submit方法可以接受runnable和callable,這裡講一下這兩者之間的區別。

我們都知道runnbale介面只有乙個run()方法,並且沒有返回值。比如上面插入學生的操作,lambda中寫的**並不關心返回值,所以這裡使用runnable就可以。但是如果我們需要關注任務執行緒的返回結果,就要使用callable了,比如下面這段**:

taskwork taskwork = new taskwork();

futurefuture = executorservice.submit(taskwork);

其中taskwork類實現了callable介面,重寫call方法。

public

class

taskwork

implements

callable

}

callable介面有乙個泛型,實現時可以隨意指定,並且call方法的返回值就是該泛型。在executorservice.submit(taskwork)之後,會返回future的例項,其中的泛型和callable中的一致。然後通過future的get方法可以獲取返回的具體物件:

returedata returndata = future.get();

執行緒池ExecutorService

執行緒池 任務提交到執行緒池,而不是直接交給某執行緒,執行緒池拿到任務後,它在內部找空閒的執行緒進行執行 封裝 任務是提交給執行緒池,乙個執行緒只能執行乙個任務,但可以同時向乙個執行緒池提交多個任務。建立固定大小的執行緒池 建立快取執行緒池 如何實現執行緒死掉後重新啟動?答案 建立單一執行緒池exe...

執行緒十四 ExecutorService

executorservice不僅能呼叫runnable的任務,它還提供了呼叫callable任務的方法。callable任務中的call方法能夠返回任務執行的結果,同時還可以丟擲受檢的異常,call方法宣告了乙個throws exception子句。為了描述executorservice的應用,我...

ExecutorService執行緒池

executorservice 建立多執行緒的步驟 1。定義執行緒類 class handler implements runnable 2。建立executorservice執行緒池 3。呼叫執行緒池操作 幾種不同的executorservice執行緒池物件 1.newcachedthreadpo...