有幾種不同的方式來將任務委托給 ExecutorService 去執行:
- execute(Runnable)
- submit(Runnable)
- submit(Callable)
- invokeAny(…)
- invokeAll(…)
execute(Runnable)
execute(Runnable) 方法要求一個 java.lang.Runnable 對象,然后對它進行異步執行。以下是使用 ExecutorService 執行一個 Runnable 的示例:
ExecutorService executorService = Executors.newSingleThreadExecutor(); executorService.execute(new Runnable() { public void run() { System.out.println("Asynchronous task"); } }); executorService.shutdown();
沒有辦法得知被執行的 Runnable 的執行結果。如果有需要的話你得使用一個 Callable(以下將做介紹)。
?
submit(Runnable)
submit(Runnable) 方法也要求一個 Runnable 實現類,但它返回一個 Future 對象。這個 Future 對象可以用來檢查 Runnable 是否已經執行完畢。
以下是 ExecutorService submit() 示例:
Future future = executorService.submit(new Runnable() { public void run() { System.out.println("Asynchronous task"); } }); future.get(); //returns null if the task has finished correctly.
?
submit(Callable)
submit(Callable) 方法類似于 submit(Runnable) 方法,除了它所要求的參數類型之外。Callable 實例除了它的 call() 方法能夠返回一個結果之外和一個 Runnable 很相像。Runnable.run() 不能夠返回一個結果。
Callable 的結果可以通過 submit(Callable) 方法返回的 Future 對象進行獲取。以下是一個 ExecutorService Callable 示例:
import java.util.concurrent.*;public class Main {public static void main(String[] args) {ExecutorService executorService = Executors.newSingleThreadExecutor();Future future = executorService.submit(new Runnable() {public void run() {try {TimeUnit.SECONDS.sleep(4);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("Asynchronous task");}});System.out.println("主方法。。。。");try {System.out.println(future.get()); //returns null if the task has finished correctly.} catch (InterruptedException e) {e.printStackTrace();} catch (ExecutionException e) {e.printStackTrace();}} }
結果:
主方法。。。。
Asynchronous task
null
future.get()會等待子線程結束后,打印出信息。
submit(Callable)
submit(Callable) 方法類似于 submit(Runnable) 方法,除了它所要求的參數類型之外。Callable 實例除了它的 call() 方法能夠返回一個結果之外和一個 Runnable 很相像。Runnable.run() 不能夠返回一個結果。
Callable 的結果可以通過 submit(Callable) 方法返回的 Future 對象進行獲取。以下是一個 ExecutorService Callable 示例:
import java.util.concurrent.*;public class Main {public static void main(String[] args) {ExecutorService executorService = Executors.newSingleThreadExecutor();Future future = executorService.submit(new Callable(){public Object call() throws Exception {TimeUnit.SECONDS.sleep(3);System.out.println("Asynchronous Callable");return "Callable Result";}});System.out.println("主方法。。。。");try {System.out.println(future.get()); //returns null if the task has finished correctly.} catch (InterruptedException e) {e.printStackTrace();} catch (ExecutionException e) {e.printStackTrace();}} }
結果:
主方法。。。。
Asynchronous Callable
Callable Result
future.get()會等待子線程結束后,打印出信息
invokeAll()
invokeAll() 方法將調用你在集合中傳給 ExecutorService 的所有 Callable 對象。invokeAll() 返回一系列的 Future 對象,通過它們你可以獲取每個 Callable 的執行結果。
記住,一個任務可能會由于一個異常而結束,因此它可能沒有 “成功”。無法通過一個 Future 對象來告知我們是兩種結束中的哪一種。
以下是一個代碼示例:
import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.concurrent.*;public class Main {public static void main(String[] args) {ExecutorService executorService = Executors.newSingleThreadExecutor();Set<Callable<String>> callables = new HashSet<Callable<String>>();callables.add(new Callable<String>() {public String call() throws Exception {System.out.println(Thread.currentThread().getName()+",Task 1");return "Task 1";}});callables.add(new Callable<String>() {public String call() throws Exception {System.out.println(Thread.currentThread().getName()+",Task 2");return "Task 2";}});callables.add(new Callable<String>() {public String call() throws Exception {System.out.println(Thread.currentThread().getName()+",Task 3");return "Task 3";}});callables.add(new Callable<String>() {public String call() throws Exception {System.out.println(Thread.currentThread().getName()+",Task 4");return "Task 4";}});callables.add(new Callable<String>() {public String call() throws Exception {System.out.println(Thread.currentThread().getName()+",Task 5");return "Task 5";}});try {List<Future<String>> futures = executorService.invokeAll(callables);for(Future<String> future : futures){System.out.println("future.get = " + future.get());}} catch (InterruptedException e) {e.printStackTrace();} catch (ExecutionException e) {e.printStackTrace();}executorService.shutdown();} }
?
結果:
pool-1-thread-1,Task 2
pool-1-thread-1,Task 5
pool-1-thread-1,Task 4
pool-1-thread-1,Task 1
pool-1-thread-1,Task 3
future.get = Task 2
future.get = Task 5
future.get = Task 4
future.get = Task 1
future.get = Task 3
?
ExecutorService 關閉
使用完 ExecutorService 之后你應該將其關閉,以使其中的線程不再運行。
比如,如果你的應用是通過一個 main() 方法啟動的,之后 main 方法退出了你的應用,如果你的應用有一個活動的 ExexutorService 它將還會保持運行。ExecutorService 里的活動線程阻止了 JVM 的關閉。
要終止 ExecutorService 里的線程你需要調用 ExecutorService 的 shutdown() 方法。ExecutorService 并不會立即關閉,但它將不再接受新的任務,而且一旦所有線程都完成了當前任務的時候,ExecutorService 將會關閉。在 shutdown() 被調用之前所有提交給 ExecutorService 的任務都被執行。
如果你想要立即關閉 ExecutorService,你可以調用 shutdownNow() 方法。這樣會立即嘗試停止所有執行中的任務,并忽略掉那些已提交但尚未開始處理的任務。無法擔保執行任務的正確執行。可能它們被停止了,也可能已經執行結束。
?
?