1. 程式人生 > >ExecutorService引發的血案(二)ExecutorService使用

ExecutorService引發的血案(二)ExecutorService使用

上一節中講到了ExecutorService中有一些管理Thread的方法

execute(Runnable)
submit(Runnable)
submit(Callable)
invokeAny(...)
invokeAll(...)

execute(Runnable)

這個方法使用的引數是 java.lang.Runnable 包中的物件,呼叫這個方法之後將會非同步執行runnable

ExecutorService executorService = Executors.newSingleThreadExecutor();

executorService.execute(new
Runnable() { public void run() { System.out.println("Asynchronous task"); } }); executorService.shutdown();

通過工廠構建一個ExecutorService例項,然後執行 自定義的Runnable,這個方法是沒有返回值的,如果你想得到一個返回值,可以使用 Callable物件替代Runnable(後面會講到)

submit(Runnable)

這個方法同execute(Runnable)一樣,都是非同步執行一個task,但是submit方法是有返回值的,它返回一個Future

物件,通過這個物件,可以檢查這個Runnable例項是否執行完成。

Future future = executorService.submit(new Runnable() {
    public void run() {
        System.out.println("Asynchronous task");
    }
});

future.get();  //returns null if the task has finished correctly.
//這個方法返回的是這個任務結束(不一定正常結束)的結果,必要的時候這個方法會等待結果出來。
//如果返回值為null,則表明這個任務已經正常的執行完畢。

submit(Callable)

這個方法的引數和submit(Runnable)不同。
Runnable和Callable的區別是,Runnable中onRun()方法是沒有返回值的,而Callable中的call()方法是有返回值的。

call()方法的返回值要如何得到呢? 可以通過 submit(Callable)方法的返回值 Future物件得到。

舉例:

Future future = executorService.submit(new Callable(){
    public Object call() throws Exception {
        System.out.println("Asynchronous Callable");
        return "Callable Result";
    }
});

System.out.println("future.get() = " + future.get());

控制檯列印的結果如下:

Asynchronous Callable
future.get() = Callable Result

invokeAny()

這個方法接收的引數是 Callable(或者Callable的實現類)物件的集合

而且這個方法並不會返回 Future物件,而是返回集合中某個Callable物件的return的值,具體是哪一個呢? 答案是:無法確認(這個跟他的機制有關),但是可以確認的是這個Callable物件是完成了的。

機制:如果 集合中的某個task,完成了(或者丟擲異常),那麼集合中剩餘的task將全部會被取消,不會得到執行。

下面是例子:

ExecutorService executorService = Executors.newSingleThreadExecutor();

Set<Callable<String>> callables = new HashSet<Callable<String>>();

callables.add(new Callable<String>() {
    public String call() throws Exception {
        return "Task 1";
    }
});
callables.add(new Callable<String>() {
    public String call() throws Exception {
        return "Task 2";
    }
});
callables.add(new Callable<String>() {
    public String call() throws Exception {
        return "Task 3";
    }
});

String result = executorService.invokeAny(callables);

System.out.println("result = " + result);

executorService.shutdown();

這個列印的結果將會是集合中的某一個Callable物件中call()方法返回的值,筆者(不是譯者)嘗試過多次,列印的結果是不同的, 有時候是 Task 1
有時候會是 Task 2 等。

invokeAll()

引數:這個方法接收的引數是 Callable(或者Callable的實現類)物件的集合

這個方法將會呼叫 集合中全部的 Callable物件。

返回值:將返回一個包含Future物件的List集合,你可以通過 list中的future物件來獲取,callable的返回值。

需要注意的是task結束的時候可能是因為 異常(沒有正常結束),所以這個task可能並沒有成功。但是通過future物件是無法判斷,task 是否成功執行 結束,還是 異常 結束。

ExecutorService executorService = Executors.newSingleThreadExecutor();

Set<Callable<String>> callables = new HashSet<Callable<String>>();

callables.add(new Callable<String>() {
    public String call() throws Exception {
        return "Task 1";
    }
});
callables.add(new Callable<String>() {
    public String call() throws Exception {
        return "Task 2";
    }
});
callables.add(new Callable<String>() {
    public String call() throws Exception {
        return "Task 3";
    }
});

List<Future<String>> futures = executorService.invokeAll(callables);

for(Future<String> future : futures){
    System.out.println("future.get = " + future.get());
}

executorService.shutdown();

ExecutorService Shutdown

當你使用ExecutorService的時候,你應該記得關閉它,這樣這些被管理的執行緒才會停止執行。

舉例:如果你的應用通過main()方法啟動,並且你的 應用中存在一個 啟用的 ExecutorService,那麼即使你的main thread(main執行緒)已經退出了,這個應用依然會在後臺執行。 原因: ExecutorService中的活躍執行緒,防止了jvm關閉ExecutorService

結論:jvm是可能無法關閉ExecutorService的,如果某些情況下,你不希望ExecutorService在後臺不受控制的執行,那你在必要的時候 需要手動呼叫 ExecutorService中的shutdown方法。

通過呼叫ExecutorService中的shutdown方法可以終止該ExecutorService中的執行緒,但是ExecutorService並不會立即關閉,但是ExecutorService已經不會再接收新的task了,等到所有的thread完成各自的task,那麼這個ExecutorService就會關閉。並且所有task中的結果 會在shutdown方法執行之前 submit(提交),都是已經執行完成了的。並不會存在沒有的執行的task。

結論:手動呼叫shutdown並不會立即關閉ExecutorService,而是等待ExecutorService中所有的任務完成,並且提交之後,才會關閉的。(所以手動呼叫shotdown方法,可以不必擔心存在剩餘任務沒有執行的情況)

如果你想立即關閉一個ExecutorService,你可以呼叫shutdownNow方法來實現。呼叫這個方法,ExecutorService將會”嘗試著“關閉所有正在執行的task,這個關閉的過程會自動跳過那些已經submit的task(節省效能)。但是 對於那些正在 執行的task,並不能保證他們就一定會直接停止執行,或許他們會暫停,或許會執行直到完成,但是ExecutorService會盡力關閉所有正在執行的task。

參考連結:連結1

相關推薦

ExecutorService引發血案ExecutorService使用

上一節中講到了ExecutorService中有一些管理Thread的方法 execute(Runnable) submit(Runnable) submit(Callable) invokeAny(...) invokeAll(...) execute

為什麼 redux 要返回一個新的 state 引發血案

Redux 的內幕(二) 一堆廢話 index.js createStore.js 來個小彩蛋 未待完續 相關連結 Redux 的內幕(二) 一堆廢話 繼上一篇文章《為什麼 redux 要返回一個新的 state 引發的血案》之後,

postgres -- 一個問題引發的事務探究

這一篇來了解下 資料庫 的隔離機制問題研究只針對Postgres 資料庫,不針對mysql或者其他。說道隔離機制,就要先說下資料庫事務的4大特性:⑴ 原子性(Atomicity)  原子性是指事務包含的所有操作要麼全部成功,要麼全部失敗回滾,這和前面兩篇部落格介紹事務的功能是

cookie系列header302跳轉引發的思考

今天我們來看以下兩個現象,並解釋這兩個現象的原因: 第一個現象:  php檔案執行過程中如果碰到有header("Location:某個頁面URL");這種語句,會直接跳轉到另一個頁面,但是這裡的跳轉並不會影響當前php檔案的繼續執行。 下面我們用程式碼跑一下看看上面的現象是否是成立的: (1

C#單元測試UnitTest--web.config檔案引發的異常

    說明:在實際的web專案中,測試的方法都是對資料庫產生操作的,然我們的資料庫連結一般放在web.config檔案中,     一個簡單的案例來模擬一下呼叫場景 1,首先我們在web.config檔案加入一個配置 <add key="awe" value

記一次傳遞檔案控制代碼引發血案

繼 記一次傳遞檔案控制代碼引發的血案 之後,這個 demo 又引發了一次血案,現錄如下。 這次我是在 linux 上測試檔案控制代碼的傳遞,linux 上並沒有 STREAMS 系統, 因此是採用 unix domain socket 的 sendmsg/recvmsg 中控制訊息部分來傳遞控制代碼的。 程式

mybatis強化Parameters和Result

pan har java onf 關系 throws efault type throw 本文通過一個簡單例子簡單記錄下參數的映射。轉載註明出處:http://www.cnblogs.com/wdfwolf3/p/6804243.html,謝謝。文件目錄如下, 1.配置文

Python 接口測試

expect type version not found 指定 刷新 created 進行 拷貝 三:http狀態碼含義(來源於w3school): 狀態碼: 1xx: 信息 消息: 描述: 100 Continue 服務器僅接收到部分請求,但是一旦

Struts2框架 Web.xml, Struts.xml, Action.Java 基本配置

str web.xml images ava img ima blog XML ges Struts2框架(二) Web.xml, Struts.xml, Action.Java 基本配置

利用css3的animation實現點點點loading動畫效果

設置 str ack rdp 提交 ssi frame spin color box-shadow實現的打點效果 簡介 box-shadow理論上可以生成任意的圖形效果,當然也就可以實現點點點的loading效果了。 實現原理 html代碼,首先需要寫如下html代

學習《第一行代碼》使用實機測試所遇問題

make 代碼 出現 onf msu field menus action java代碼 實機使用酷派大神F1,添加menu後,右上角不出現菜單,此時在java代碼中加入以下方法在onCreate中運行 private void makeActionOverflowMenu

python的列表

數字0 linux play 字符串 pytho head 生成 index color 1、遍歷整個列表 #for 循環 # >>> name_list[‘faker‘, ‘dopa‘, ‘gogoing‘, ‘uzi‘] >>>

JAVA學習第十九課java程序的異常處理

num 函數 錯誤 style col 編譯失敗 return [] java 異常處理的捕捉形式: 這是能夠對異常進行針對性處理的方式 六、try、catch的理解 詳細格式: try { //須要被檢測異常的代碼 } catch(異常類 變量)//改變量用

遠程協助開發總結

控制 amp 為什麽不能 username 開發 col dsc exce nec 遠程協助開發的過程中繼續總結 針對開發總結一的問題,改正了一些地方 1.圖像和命令采用兩個套接字,為什麽不能采用一個套接字?遠程協助是快頻的通信,圖像需要不間斷的從受控端發送到控制端,發送接

Java內存模型——重排序

序列 依賴性 種類 如果 禁止 加載 runtime 屬於 style 一、重排序   重排序是指為了提高程序的執行效率,編譯器和處理器常常會對語句的執行順序或者指令的執行順序進行重排。 編譯器優化的重排序:編譯器在不改變單線程程序語義的前提下,可以重新安排語句的執行順序

java.util包詳解——Connection接口

操作 相同 元素 叠代 cat roo soft true nbsp Connection接口介紹   Connection接口是java集合的root接口,沒有實現類,只有子接口和實現子接口的各種容器。主要用來表示java集合這一大的抽象概念。   Connection接

沖刺階段

什麽 開始 bsp 初步 感覺 困難 用戶登陸 問題 代碼 昨天做了什麽: 制作關於老師用戶登陸的網站界面,初步制定了功能。 今天要做什麽: 開始寫界面的代碼,設計界面和功能的初步代碼。 遇到什麽困難: 對於界面設計問題不大,主要是

mysql進階之細談索引、分頁與慢日誌

連表 組合索引 rar 偏移量 最小值 num glob 要求 for 索引 1、數據庫索引   數據庫索引是一種數據結構,可以以額外的寫入和存儲空間為代價來提高數據庫表上的數據檢索操作的速度,以維護索引數據結構。索引用於快速定位數據,而無需在每次訪問數據庫表時搜索數據

一篇文章快速了解 量子計算機 精心整理

難題 表示 學技術 公司 如何實現 lan 文章 區分 核心 好了,下面轉入量子計算機的總結: 有趣的量子理論 量子論的一些基本論點顯得並不“玄乎”,但它的推論顯得很“玄”。我們假設一個“量子”距離也就是最小距離的兩個端點A和B。按照量子論,物體從A不經過A和B中的

數據結構:線性表的使用原則以及鏈表的應用-稀疏矩陣的三元組表示

查找 triple 表的操作 結構 循環鏈表 循環 大於 ria 幫助 上一篇博文中主要總結線性表中的鏈式存儲結構實現,比方單向鏈表、循環鏈表。還通過對照鏈表和順序表的多項式的存儲表示。說明鏈表的長處。能夠參看上篇博文http://blog.csdn.net/lg125