一、概述
execute和submit都是執行緒池中執行任務的方法。
execute是Executor
介面中的方法
public interface Executor {
void execute(Runnable command);
}
submit是ExecuteService
介面中的方法。
public interface ExecutorService extends Executor {
<T> Future<T> submit(Callable<T> task);
<T> Future<T> submit(Runnable task, T result);
Future<?> submit(Runnable task);
}
透過原始碼可以看出execute
方法無返回值,引數為Runnable
物件。
submit
方法有三個過載方法,都有Future
型別的返回值,引數可以是Runnable
物件,Callable
物件,Runnable
物件和一個其他型別的物件。
那麼在執行過程中有異常丟擲會怎麼樣呢,先說答案,execute方法會直接丟擲異常,submit方法不會丟擲異常,只有在透過Future的get方法獲取結果的時候才會丟擲異常,下面進行測試:
public class ExecutorTest1 {
public static void main(String[] args) {
ExecutorService executorService = Executors.newSingleThreadExecutor();
ExecutorTest1 test1 = new ExecutorTest1();
executorService.execute(() -> test1.say("execute方法"));
executorService.submit(() -> test1.say("submit方法"));
executorService.shutdown();
}
private void say(String msg){
System.out.println(msg);
throw new RuntimeException("丟擲了異常:"+ msg);
}
}
執行結果如下:
可見execute方法直接丟擲了異常,submit方法只列印了引數沒有丟擲異常,下面測試使用Future的get方法獲取結果:
public class ExecutorTest1 {
public static void main(String[] args) {
ExecutorService executorService = Executors.newSingleThreadExecutor();
ExecutorTest1 test1 = new ExecutorTest1();
executorService.execute(() -> test1.say("execute方法"));
Future<?> submitFuture = executorService.submit(() -> test1.say("submit方法"));
try {
Object o = submitFuture.get();
System.out.println("這是submit的返回值:"+o);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
executorService.shutdown();
}
private void say(String msg){
System.out.println(msg);
throw new RuntimeException("丟擲了異常:"+ msg);
}
}
結果如下:
可見使用submit方法時只有在使用Future的get方法時才會丟擲異常,並且get方法也會丟擲ExecutionException
異常。
那麼還有一個問題,如果執行緒中執行方法丟擲的異常已經被捕獲了,那麼submit會怎麼處理呢,其實在方法中如果異常已經被捕獲了,那麼就是方法的正常執行,有異常列印的話在執行的時候就會列印,不會等到呼叫Future的get方法時候才會列印。測試如下:
public class ExecutorTest1 {
public static void main(String[] args) {
ExecutorService executorService = Executors.newSingleThreadExecutor();
ExecutorTest1 test1 = new ExecutorTest1();
executorService.execute(() -> test1.say("execute方法"));
Future<?> submitFuture = executorService.submit(() -> test1.say("submit方法"));
try {
Object o = submitFuture.get();
System.out.println("這是submit的返回值:"+o);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
executorService.shutdown();
}
private void say(String msg){
System.out.println(msg);
try{
throw new RuntimeException("丟擲了異常:"+ msg);
}catch (Exception e){
e.printStackTrace();
}
}
}
結果如下:
可見execute和submit都正常執行了方法,Future的get方法也獲取到了結果,因為say方法沒有返回值,所以列印的結果是null。
二、結論
execute和submit的區別如下:
- execute是Executor介面的方法,submit是ExecuteService介面的方法。
- execute的入參是Runnable,submit的入參可以是Runnable、Callable、Runnable和一個返回值。
- execute沒有返回值,submit有返回值。
- 方法中丟擲異常,execute會直接丟擲異常,submit會在獲取結果的時候丟擲異常,如果不獲取結果,submit不丟擲異常。
關於Future可以檢視:
Java多執行緒:Future和FutureTask
之前文章: