橋西網(wǎng)站建設(shè)推廣引流渠道有哪些
點(diǎn)個(gè)關(guān)注,必回關(guān)
文章目錄
- 一. execute和submit的區(qū)別與聯(lián)系
- 1、測(cè)試代碼的整體框架如下:
- 2、首先研究Future<?> submit(Runnable task)和void execute(Runnable command),
- 3、submit(Runnable task, T result) 方法可以使submit執(zhí)行完Runnable任務(wù)后返回指定的返回值。
- 4、submit(Callable<T> task)這個(gè)方法沒什么好說(shuō)的,用來(lái)提交Callable類型任務(wù),返回值由call方法決定。
- 5、關(guān)于execute和submit遭遇異常的表現(xiàn)
一. execute和submit的區(qū)別與聯(lián)系
- execute和submit都屬于線程池的方法,execute只能提交Runnable類型的任務(wù),而submit既能提交Runnable類型任務(wù)也能提交哦啊Callable類型任務(wù)
- execute會(huì)直接拋出任務(wù)執(zhí)行時(shí)的異常,submit會(huì)吃掉異常,可以通過(guò)Future的get方法將任務(wù)執(zhí)行時(shí)的異常重新拋出
- execute所屬頂層接口是Executor,submit所屬頂層接口是ExecutorService,實(shí)現(xiàn)類ThreadPoolExecutor重寫了execute方法,抽象類AbstractExecutorService重寫了submit方法。
submit和execute由于參數(shù)不同有四種實(shí)現(xiàn)形式,
如下所示,本文主要研究這四種形式在各自使用場(chǎng)景下的區(qū)別和聯(lián)系
<T> Future<T> submit(Callable<T> task);
<T> Future<T> submit(Runnable task, T result);
Future<?> submit(Runnable task);
void execute(Runnable command);
關(guān)于Runnable和Callable任務(wù)如果你還存在疑惑,建議你先看看我的另一篇文章Runnable和Callable的區(qū)別和聯(lián)系。
1、測(cè)試代碼的整體框架如下:
import java.util.concurrent.*;public class TestSubmitAndExecute {static ExecutorService executor = Executors.newCachedThreadPool();public static void main(String[] args) {initExecutors();/**put test codes here*//***/waitToTerminated();}private static void initExecutors() {if (executor.isTerminated()) {executor = Executors.newCachedThreadPool();}}private static void waitToTerminated() {executor.shutdown();while (!executor.isTerminated()) {}}/*** 測(cè)試 submit(Callable<T> task)** @param callable* @param <T>* @return*/public static <T> T testSubmitCallable(Callable callable) {Future<T> future = executor.submit(callable);T result = null;try {result = future.get();} catch (InterruptedException e) {e.printStackTrace();} catch (ExecutionException e) {e.printStackTrace();}return result;}/*** 測(cè)試submit(Runnable task, T result)** @param runnable* @param t* @param <T>* @return*/public static <T> T testSubmitRunnable(Runnable runnable, T t) {Future<T> future = executor.submit(runnable, t);T result = null;try {result = future.get();} catch (InterruptedException e) {e.printStackTrace();} catch (ExecutionException e) {e.printStackTrace();}return result;}/*** 測(cè)試 submit(Runnable task)* submit提交Runnable任務(wù)會(huì)默認(rèn)返回null** @param runnable* @return*/public static Object testSubmitRunnable(Runnable runnable) {Future<?> future = executor.submit(runnable);Object v = null;try {v = future.get();} catch (InterruptedException e) {e.printStackTrace();} catch (ExecutionException e) {e.printStackTrace();}return v;}/*** 測(cè)試 execute(Runnable command)* execute會(huì)直接拋出異常,submit只有通過(guò)調(diào)用Future對(duì)象的get方法才能獲取異常** @param runnable*/public static void testExecuteRunnable(Runnable runnable) {executor.execute(runnable);}
}
這個(gè)測(cè)試框架提供了4個(gè)靜態(tài)方法用來(lái)測(cè)試submit和execute總共包含的四種表現(xiàn)形式,除此之外提供initExecutors用于提前檢測(cè)線程池是否終止,若終止則初始化,waitToTerminated方法用于關(guān)閉線程池,并阻塞到線程池終止為止。
除了測(cè)試框架之外提供了4個(gè)不同的任務(wù),分別測(cè)試Callable和Runnable在拋異常時(shí)的表現(xiàn)形式。
class CallableTask implements Callable<Integer> {@Overridepublic Integer call() throws Exception {int sum = 0;for (int i = 0; i < 520; i++) {sum += i;}return sum;}
}/*** 會(huì)拋異常的CallableTask*/
class ExceptionCallableTask implements Callable<Boolean> {public Boolean call() throws Exception {int num = 1 / 0;return false;}
}class RunnableTask implements Runnable {@Overridepublic void run() {System.out.println("I am a runnable task");}
}/*** 會(huì)拋異常的RunnableTask*/
class ExceptionRunableTask implements Runnable {@Overridepublic void run() {int num = 1 / 0;}
}
整體結(jié)構(gòu)搭起來(lái),下來(lái)就是研究具體差異的時(shí)刻了。
2、首先研究Future<?> submit(Runnable task)和void execute(Runnable command),
這兩個(gè)方法都是執(zhí)行Runnable類型任務(wù),前者有返回值,但是返回值為null,后者無(wú)返回值。
public static void main(String[] args) {initExecutors();/**put test codes here*/Object object = testSubmitRunnable(new RunnableTask());System.out.println(object);testExecuteRunnable(new RunnableTask());/***/waitToTerminated();}
很容易觀察控制臺(tái)輸出如下:
I am a runnable task
null
I am a runnable task
可以看出submit執(zhí)行Runnable類型任務(wù)時(shí)默認(rèn)返回值為null。如果我們需要submit在提交Runnable任務(wù)可以返回非空,就需要用到submit的另外一個(gè)重載的方法: Future submit(Runnable task, T result);
3、submit(Runnable task, T result) 方法可以使submit執(zhí)行完Runnable任務(wù)后返回指定的返回值。
main方法如下:
public static void main(String[] args) {initExecutors();/**put test codes here*/
// Object object = testSubmitRunnable(new RunnableTask());
// System.out.println(object);
//
// testExecuteRunnable(new RunnableTask());Integer i = testSubmitRunnable(new RunnableTask(), 3);System.out.println(i);Boolean bool = testSubmitRunnable(new RunnableTask(), true);System.out.println(bool);String str = testSubmitRunnable(new RunnableTask(), "你好嗎");System.out.println(str);/***/waitToTerminated();}
控制臺(tái)輸出:
I am a runnable task
3
I am a runnable task
true
I am a runnable task
你好嗎
可以看出我們輸入的什么參數(shù),任務(wù)執(zhí)行完畢后就返回什么參數(shù)。
4、submit(Callable task)這個(gè)方法沒什么好說(shuō)的,用來(lái)提交Callable類型任務(wù),返回值由call方法決定。
main方法如下:
public static void main(String[] args) {initExecutors();/**put test codes here*/
// Object object = testSubmitRunnable(new RunnableTask());
// System.out.println(object);
//
// testExecuteRunnable(new RunnableTask());// Integer i = testSubmitRunnable(new RunnableTask(), 3);
// System.out.println(i);
//
// Boolean bool = testSubmitRunnable(new RunnableTask(), true);
// System.out.println(bool);
//
// String str = testSubmitRunnable(new RunnableTask(), "你好嗎");
// System.out.println(str);Object o = testSubmitCallable(new CallableTask());System.out.println(o);/***/waitToTerminated();}
CallableTask的執(zhí)行邏輯是計(jì)算0到520之間的所有整數(shù)之和,所以控制臺(tái)輸出:
134940
5、關(guān)于execute和submit遭遇異常的表現(xiàn)
execute直接將任務(wù)執(zhí)行時(shí)期的異常拋出,main方法和控制臺(tái)打印分別如下:
public static void main(String[] args) {initExecutors();/**put test codes here*/
// Object object = testSubmitRunnable(new RunnableTask());
// System.out.println(object);
//
// testExecuteRunnable(new RunnableTask());// Integer i = testSubmitRunnable(new RunnableTask(), 3);
// System.out.println(i);
//
// Boolean bool = testSubmitRunnable(new RunnableTask(), true);
// System.out.println(bool);
//
// String str = testSubmitRunnable(new RunnableTask(), "你好嗎");
// System.out.println(str);// Object o = testSubmitCallable(new CallableTask());
// System.out.println(o);testExecuteRunnable(new ExceptionRunableTask());/***/waitToTerminated();}
Exception in thread "pool-1-thread-1" java.lang.ArithmeticException: / by zeroat ExceptionRunableTask.run(TestRunnableAndCallable.java:38)at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)at java.lang.Thread.run(Thread.java:745)
submit比較特殊,如果沒有通過(guò)Future.get來(lái)獲取結(jié)算結(jié)果,則吃掉異常。先將測(cè)試方法稍做調(diào)整,修改成如下形式:
/*** 測(cè)試 submit(Callable<T> task)** @param callable* @param <T>* @return*/public static <T> T testSubmitCallable(Callable callable) {Future<T> future = executor.submit(callable);T result = null;/*try {result = future.get();} catch (InterruptedException e) {e.printStackTrace();} catch (ExecutionException e) {e.printStackTrace();}*/return result;}
當(dāng)我們?cè)趍ain方法添加如下代碼時(shí),控制臺(tái)其實(shí)沒有打印任何異常
public static void main(String[] args) {initExecutors();/**put test codes here*/
// Object object = testSubmitRunnable(new RunnableTask());
// System.out.println(object);
//
// testExecuteRunnable(new RunnableTask());// Integer i = testSubmitRunnable(new RunnableTask(), 3);
// System.out.println(i);
//
// Boolean bool = testSubmitRunnable(new RunnableTask(), true);
// System.out.println(bool);
//
// String str = testSubmitRunnable(new RunnableTask(), "你好嗎");
// System.out.println(str);// Object o = testSubmitCallable(new CallableTask());
// System.out.println(o);// testExecuteRunnable(new ExceptionRunableTask());testSubmitCallable(new ExceptionCallableTask());/***/waitToTerminated();}
**```
如果將testSubmitCallable代碼中被注釋的部分取消注釋,則可以看到異常信息如下:**```bash
java.util.concurrent.ExecutionException: java.lang.ArithmeticException: / by zeroat java.util.concurrent.FutureTask.report(FutureTask.java:122)at java.util.concurrent.FutureTask.get(FutureTask.java:192)at TestSubmitAndExecute.testSubmitCallable(TestSubmitAndExecute.java:58)at TestSubmitAndExecute.main(TestSubmitAndExecute.java:28)
Caused by: java.lang.ArithmeticException: / by zeroat ExceptionCallableTask.call(TestRunnableAndCallable.java:20)at ExceptionCallableTask.call(TestRunnableAndCallable.java:18)at java.util.concurrent.FutureTask.run(FutureTask.java:266)at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)at java.lang.Thread.run(Thread.java:745)
關(guān)于execute和submit的簡(jiǎn)單研究到此結(jié)束,謝謝。