Java中的線程池在進行任務提交時,有兩種方式:execute和submit方法。
一、execute和submit的區別
- execute只能提交Runnable類型的任務,無返回值。submit既可以提交Runnable類型的任務,也可以提交Callable類型的任務,會有一個類型為Future的返回值,但當任務類型為Runnable時,返回值為null。
- execute在執行任務時,如果遇到異常會直接拋出,而submit不會直接拋出,只有在使用Future的get方法獲取返回值時,才會拋出異常。
測試代碼:
package com.javaBase.LineDistancePond; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * 〈一句話功能簡述〉; * 〈execute與submit的區別〉 * * @author jxx * @see [相關類/方法](可選) * @since [產品/模塊版本] (可選) */ public class TestThreadPoolBegin { public static void main(String[] args) throws Exception{ ExecutorService es = Executors.newSingleThreadExecutor(); Runnable runnable = new Runnable() { @Override public void run() { System.out.println("Runnable線程處理開始..."); int a = 0; int b = 3; System.out.println("除以0的結果為:" + b/a); System.out.println("Runnable線程處理結束..."); } }; es.execute(runnable); es.shutdown(); } }
執行結果:
Exception in thread "pool-1-thread-1" java.lang.ArithmeticException: / by zero Runnable線程處理開始... at com.javaBase.LineDistancePond.TestThreadPoolBegin$1.run(TestThreadPoolBegin.java:24) 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) Process finished with exit code 0
package com.javaBase.LineDistancePond; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * 〈一句話功能簡述〉; * 〈execute與submit的區別〉 * * @author jxx * @see [相關類/方法](可選) * @since [產品/模塊版本] (可選) */ public class TestThreadPoolBegin { public static void main(String[] args) throws Exception{ ExecutorService es = Executors.newSingleThreadExecutor(); Runnable runnable = new Runnable() { @Override public void run() { System.out.println("Runnable線程處理開始..."); int a = 0; int b = 3; System.out.println("除以0的結果為:" + b/a); System.out.println("Runnable線程處理結束..."); } }; es.submit(runnable); es.shutdown(); } }
執行結果:
Runnable線程處理開始...
Process finished with exit code 0
package com.javaBase.LineDistancePond; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; /** * 〈一句話功能簡述〉; * 〈execute與submit的區別〉 * * @author jxx * @see [相關類/方法](可選) * @since [產品/模塊版本] (可選) */ public class TestThreadPoolBegin { public static void main(String[] args) throws Exception{ ExecutorService es = Executors.newSingleThreadExecutor(); Callable callable = new Callable() { @Override public Object call() throws Exception { System.out.println("線程處理開始..."); int a = 0; int b = 3; System.out.println("除以0的結果為:" + b/a); System.out.println("線程處理結束..."); return "0"; } }; Future<String> future = es.submit(callable); System.out.println("任務執行完成,結果為:" + future.get()); } }
執行結果:
Exception in thread "main" java.util.concurrent.ExecutionException: java.lang.ArithmeticException: / by zero at java.util.concurrent.FutureTask.report(FutureTask.java:122) at java.util.concurrent.FutureTask.get(FutureTask.java:192) at com.javaBase.LineDistancePond.TestThreadPoolBegin.main(TestThreadPoolBegin.java:32) Caused by: java.lang.ArithmeticException: / by zero at com.javaBase.LineDistancePond.TestThreadPoolBegin$1.call(TestThreadPoolBegin.java:26) 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) 線程處理開始...
二、submit的get方法
future的get方法在未獲得返回值之前會一直阻塞,我們可以使用future的isDone方法判斷任務是否執行完成,然后再決定是否get,因此上述代碼我們可以優化如下:
package com.javaBase.LineDistancePond; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; /** * 〈一句話功能簡述〉; * 〈execute與submit的區別〉 * * @author jxx * @see [相關類/方法](可選) * @since [產品/模塊版本] (可選) */ public class TestThreadPoolBegin { public static void main(String[] args) throws Exception{ ExecutorService es = Executors.newSingleThreadExecutor(); Callable callable = new Callable() { @Override public String call() throws Exception { System.out.println("線程處理開始..."); int a = 2; int b = 3; System.out.println("3/2的結果為:" + b/a); System.out.println("線程處理結束..."); return "0"; } }; Future<String> future = es.submit(callable); while(true) { //idDone:如果任務已完成,則返回 true。 可能由於正常終止、異常或取消而完成,在所有這些情況中,此方法都將返回 true。 if(future.isDone()) { System.out.println("任務執行完成:" + future.get()); break; } } es.shutdown(); } }
執行結果:
線程處理開始... 3/2的結果為:1 線程處理結束... 線程執行完成:0 Process finished with exit code 1