1. 程式人生 > >ExecutorService的execute和submit方法

ExecutorService的execute和submit方法

因為之前一直是用的execute方法,最近有個情況需要用到submit方法,所以研究了下。

三個區別:

1、接收的引數不一樣

2、submit有返回值,而execute沒有

Method submit extends base method Executor.execute by creating and returning a Future that can be used to cancel execution and/or wait for completion. 

用到返回值的例子,比如說我有很多個做validation的task,我希望所有的task執行完,然後每個task告訴我它的執行結果,是成功還是失敗,如果是失敗,原因是什麼。然後我就可以把所有失敗的原因綜合起來發給呼叫者。

個人覺得cancel execution這個用處不大,很少有需要去取消執行的。

而最大的用處應該是第二點。

3、submit方便Exception處理

There is a difference when looking at exception handling. If your tasks throws an exception and if it was submitted with execute this exception will go to the uncaught exception handler (when you don't have provided one explicitly, the default one will just print the stack trace to System.err

). If you submitted the task with submit any thrown exception, checked or not, is then part of the task's return status. For a task that was submitted with submit and that terminates with an exception, the Future.get will rethrow this exception, wrapped in an ExecutionException.

意思就是如果你在你的task裡會丟擲checked或者unchecked exception,而你又希望外面的呼叫者能夠感知這些exception並做出及時的處理,那麼就需要用到submit,通過捕獲Future.get丟擲的異常。

比如說,我有很多更新各種資料的task,我希望如果其中一個task失敗,其它的task就不需要執行了。那我就需要catch Future.get丟擲的異常,然後終止其它task的執行,程式碼如下:

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class ExecutorServiceTest {
	public static void main(String[] args) {
		ExecutorService executorService = Executors.newCachedThreadPool();
		List<Future<String>> resultList = new ArrayList<Future<String>>();

		// 建立10個任務並執行
		for (int i = 0; i < 10; i++) {
			// 使用ExecutorService執行Callable型別的任務,並將結果儲存在future變數中
			Future<String> future = executorService.submit(new TaskWithResult(i));
			// 將任務執行結果儲存到List中
			resultList.add(future);
		}
		executorService.shutdown();

		// 遍歷任務的結果
		for (Future<String> fs : resultList) {
			try {
				System.out.println(fs.get()); // 列印各個執行緒(任務)執行的結果
			} catch (InterruptedException e) {
				e.printStackTrace();
			} catch (ExecutionException e) {
				executorService.shutdownNow();
				e.printStackTrace();
				return;
			}
		}
	}
}

class TaskWithResult implements Callable<String> {
	private int id;

	public TaskWithResult(int id) {
		this.id = id;
	}

	/**
	 * 任務的具體過程,一旦任務傳給ExecutorService的submit方法,則該方法自動在一個執行緒上執行。
	 * 
	 * @return
	 * @throws Exception
	 */
	public String call() throws Exception {
		System.out.println("call()方法被自動呼叫,幹活!!!             " + Thread.currentThread().getName());
		if (new Random().nextBoolean())
			throw new TaskException("Meet error in task." + Thread.currentThread().getName());
		// 一個模擬耗時的操作
		for (int i = 999999999; i > 0; i--)
			;
		return "call()方法被自動呼叫,任務的結果是:" + id + "    " + Thread.currentThread().getName();
	}
}

class TaskException extends Exception {
	public TaskException(String message) {
		super(message);
	}
}

執行的結果類似於:
call()方法被自動呼叫,幹活!!!             pool-1-thread-1
call()方法被自動呼叫,幹活!!!             pool-1-thread-2
call()方法被自動呼叫,幹活!!!             pool-1-thread-3
call()方法被自動呼叫,幹活!!!             pool-1-thread-5
call()方法被自動呼叫,幹活!!!             pool-1-thread-7
call()方法被自動呼叫,幹活!!!             pool-1-thread-4
call()方法被自動呼叫,幹活!!!             pool-1-thread-6
call()方法被自動呼叫,幹活!!!             pool-1-thread-7
call()方法被自動呼叫,幹活!!!             pool-1-thread-5
call()方法被自動呼叫,幹活!!!             pool-1-thread-8
call()方法被自動呼叫,任務的結果是:0    pool-1-thread-1
call()方法被自動呼叫,任務的結果是:1    pool-1-thread-2
java.util.concurrent.ExecutionException: com.cicc.pts.TaskException: Meet error in task.pool-1-thread-3
	at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:222)
	at java.util.concurrent.FutureTask.get(FutureTask.java:83)
	at com.cicc.pts.ExecutorServiceTest.main(ExecutorServiceTest.java:29)
Caused by: com.cicc.pts.TaskException: Meet error in task.pool-1-thread-3
	at com.cicc.pts.TaskWithResult.call(ExecutorServiceTest.java:57)
	at com.cicc.pts.TaskWithResult.call(ExecutorServiceTest.java:1)
	at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
	at java.util.concurrent.FutureTask.run(FutureTask.java:138)
	at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
	at java.lang.Thread.run(Thread.java:619)
可以看見一旦某個task出錯,其它的task就停止執行。

相關推薦

ExecutorService的executesubmit方法

因為之前一直是用的execute方法,最近有個情況需要用到submit方法,所以研究了下。 三個區別: 1、接收的引數不一樣 2、submit有返回值,而execute沒有 Method submit extends base method Executor.execut

Java ExecutorService中execute()submit()方法的區別

方法execute()沒有返回值,而submit()方法可以有返回值(通過Callable和Future介面) 方法execute()在預設情況下異常直接丟擲(即列印堆疊資訊),不能捕獲,但是可以通過

執行緒池submitexecute方法區別(類似callablerunnable)

執行緒池中的execute方法大家都不陌生,即開啟執行緒執行池中的任務。還有一個方法submit也可以做到,它的功能是提交指定的任務去執行並且返回Future物件,即執行的結果。下面簡要介紹一下兩者的三個區別: 1、接收的引數不一樣 2、submit有返回值,而execute沒有 用到返

執行緒池的submitexecute方法區別

執行緒池中的execute方法大家都不陌生,即開啟執行緒執行池中的任務。還有一個方法submit也可以做到,它的功能是提交指定的任務去執行並且返回Future物件,即執行的結果。下面簡要介紹一下兩者的三個區別: 1、接收的引數不一樣 2、submit有返回值,而exe

血的教訓--如何正確使用執行緒池submitexecute方法

血的教訓之背景:使用執行緒池對存量資料進行遷移,但是總有一批資料遷移失敗,無異常日誌列印 凶案起因 ​ 聽說parallelStream並行流是個好東西,由於日常開發stream序列流的場景比較多,這次需要寫遷移程式剛好可以用得上,那還不趕緊拿來裝*一下,此時不裝更待何時。機智的我還知道在 JVM 的後臺

web測試中的測試點測試方法總結

動態 小數 圖片尺寸 提示信息 方便 margin style 容錯性 字符型 測試是一種思維,包括情感思維和智力思維,情感思維主要體現在一句俗語:思想決定行動上(要懷疑一切),智力思維主要體現在測試用例的設計上。具有了這樣的思想,就會找出更多的bug。 一、輸入框

函數中的私有變量特權方法

getc 單例 隱藏數據 需要 接口 返回對象 div 外部 his 定義   【1】【私有變量】  任何在函數中定義的變量,都可以認為是私有變量,因為不能在函數外部訪問這些變量。私有變量包括函數的參數、局部變量和在函數內部定義的其他函數   【2】【特權方法】  如果在函

[C#學習筆記之異步編程模式2]BeginInvokeEndInvoke方法 (轉載)

cti otf 函數返回 編程模式 catch 數值 gin 單線程 blog 為什麽要進行異步回調?眾所周知,普通方法運行,是單線程的,如果中途有大型操作(如:讀取大文件,大批量操作數據庫,網絡傳輸等),都會導致方法阻塞,表現在界面上就是,程序卡或者死掉,界面元素不動了,

jquery中prop()方法attr()方法的區別淺析

clas ttr over dex idt pro query selected accesskey jquery1.6中新加了一個方法prop(),一直沒用過它,官方解釋只有一句話:獲取在匹配的元素集中的第一個元素的屬性值。 大家都知道有的瀏覽器只要寫disabled,c

scroll()scrollTop()方法——實現電商網站中的電梯導航

窗口 css樣式 ram 每一個 最新 top index hid none 要想實現電商網站的電梯導航效果,首先需要了解以下知識點: jquery 事件 - scroll() 方法 對元素滾動的次數進行計數,當用戶滾動指定的元素時,會發生 scroll 事件。scroll

【設計模式】簡單工廠模式工廠方法模式

產生 for plm nbsp osc rbm play stp mage > 簡單工廠模式 顧名思義,此模式的設計結構是簡單的,核心是生產對象。 一般來說,運用工廠模式生產的對象應該是構建對象的過程比較復雜的,獲取構建對象的過程在日後可能發生變更的。 簡單工廠

小胖說事28------iOS中extern,staticconst差別使用方法

方法 string 文件 only 聲明 sans nbsp ring const 通俗的講: extern字段使用的時候,聲明的變量為全局變量,都能夠調用,也有這樣一種比較狹義的說法:extern能夠擴展一個類中的變量到還有一個類中;

python基礎2-靜態方法方法

變量 img 靜態 訪問 func title 改變 參數 code 1. 類方法 是類對象所擁有的方法,需要用修飾器@classmethod來標識其為類方法,對於類方法,第一個參數必須是類對象,一般以cls作為第一個參數(當然可以用其他名稱的變量作為其第一個參數,但是大部

forEachmapfor方法的區別

turn 而不是 ber num 遍歷數組 風格 cnblogs ron () 那麽接下來,我繼續做分析,為什麽更推薦用.map(),而不是.forEach()? 首先,.map()要比.forEach()執行速度更快。雖然我也說過執行速度不是我們需要考慮的主要因素,但是他

為什麽使用 Arrays.asList()得到的集合,使用remove( ) add( )方法會拋出unsupportedoperationexception(不支持操作異常)

操作 err move lan 16px exceptio operation amp span  這是由於:    Arrays.asList() 返回java.util.Arrays$ArrayList, 而不是ArrayList。 Arrays$ArrayList

JavaScript中閉包實現的私有屬性的getter()setter()方法

參數 strong prop nbsp body 利用 edi 獲取 展示 註意: 以下的輸出都在瀏覽器的控制臺中 <!DOCTYPE html> <html> <head> <meta charset="utf-8"&g

反射機制--調用構造函數成員方法、制作幫助文檔

port const center 分享 相關 src -- 知識 water 今天學習了關於反射的相關知識,通過反射能夠找到類中的構造方法和全部的成員方法。而並不了解這個類的構造的人能夠非常方便的運用反射機制。 掌握發射主要了解這幾個類,類位於java.long.re

call 方法 apply方法

his comm 應用 [] () itl new 語法 常用 1、方法定義 call方法: 語法:call([thisObj[,arg1[, arg2[, [,.argN]]]]]) 定義:調用一個對象的一個方法,以另一個對象替換當前對象。 說明: call 方法可以

IP地址的規劃設計方法(三)

情況 網絡 fill 路由 十六進制 fonts 網絡管理 協議 討論 九,內部網絡專用IP地址規劃與網絡地址轉換NAT方法 (1)內部網絡的專用IP地址選擇的根據 RFC1918在討論內部網絡的專用IP地址規劃方法時任務

call apply方法解析

ray ntb 方法 綁定 推斷 都是 還要 new int32 ECAMScript 3給Function的原型定義了兩個方法,它們是Function.prototype.call和Function. prototype.apply。在實際開發中,特別是在一些函數式風格的