JAVA中ThreadPoolExecutor執行緒池的submit方法詳解
下面小編就為大家帶來一篇簡單談談ThreadPoolExecutor線程池之submit方法。小編覺得蠻不錯的,現在就分享給大家,也給大家做個參考。一起跟著小編過來看看吧
jdk1.7.0_79
在上一篇《ThreadPoolExecutor線程池原理及其execute方法》中提到了線程池ThreadPoolExecutor的原理以及它的execute方法。本文解析ThreadPoolExecutor#submit。
對於一個任務的執行有時我們不需要它回傳結果,但是有我們需要它的回傳執行結果。對於執行緒來講,如果不需要它回傳結果則實作Runnable,而如果需要執行結果的話則可以實作Callable。在執行緒池同樣execute提供一個不需要傳回結果的任務執行,而對於需要結果傳回的則可呼叫其submit方法。
回顧ThreadPoolExecutor的繼承關係。
在Executor介面中只定義了execute方法,而submit方法則是在ExecutorService介面中定義的。
//ExecutorService public interface ExecutorService extends Executor { ... <T> Future<T> submit(Callable<T> task); <T> Future<T> submit(Runnable task, T result); <T> Future<T> submit(Runnable task); ... }
而在其子類別AbstractExecutorService實作了submit方法。
//AbstractExecutorService public abstract class AbstractExecutorService implements ExecutorService { ... public <T> Future<T> submit(Callable<T> task) { if (task == null) throw new NullPointerException(); RunnableFuture<T> ftask = newTaskFor(task); execute(ftask); return ftask; } public <T> Future<T> submit(Runnable task, T result) { if (task == null) throw new NullPointerException(); RunnableFuture<T> ftask = newTaskFor(task); execute(ftask); return ftask; } public Future<?> submit(Runnable task) { if (task == null) throw new NullPointerExeption(); RunnableFuture<Void> ftask = newTaskFor(task, null); execute(ftask); return ftask; } ... }
在AbstractExecutorService實現的submit方法實際上是一個模板方法,定義了submit方法的演算法骨架,其execute交給了子類別。 (可以看到在許多原始碼中,模板方法模式被大量運用,有關模板方法模式可參考《模板方法模式》)
儘管submit方法能提供線程執行的返回值,但只有實現了Callable才會有回傳值,而實作Runnable的執行緒則是沒有回傳值的,也就是說在上面的3個方法中,submit(Callable
下面給3個例子,來感受下submit方法。
submit(Callable
package com.threadpoolexecutor; import java.util.concurrent.*; /** * ThreadPoolExecutor#sumit(Callable<T> task) * Created by yulinfeng on 6/17/17. */ public class Sumit1 { public static void main(String[] args) throws ExecutionException, InterruptedException { Callable<String> callable = new Callable<String>() { public String call() throws Exception { System.out.println("This is ThreadPoolExetor#submit(Callable<T> task) method."); return "result"; } }; ExecutorService executor = Executors.newSingleThreadExecutor(); Future<String> future = executor.submit(callable); System.out.println(future.get()); } }
submit(Runnable task, T result)
#package com.threadpoolexecutor; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; /** * ThreadPoolExecutor#submit(Runnable task, T result) * Created by yulinfeng on 6/17/17. */ public class Submit2 { public static void main(String[] args) throws ExecutionException, InterruptedException { ExecutorService executor = Executors.newSingleThreadExecutor(); Data data = new Data(); Future<Data> future = executor.submit(new Task(data), data); System.out.println(future.get().getName()); } } class Data { String name; public String getName() { return name; } public void setName(String name) { this.name = name; } } class Task implements Runnable { Data data; public Task(Data data) { this.data = data; } public void run() { System.out.println("This is ThreadPoolExetor#submit(Runnable task, T result) method."); data.setName("kevin"); } }
#submit(Runnable task)
package com.threadpoolexecutor; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; /** * ThreadPoolExecutor#sumit(Runnable runnables) * Created by yulinfeng on 6/17/17. */ public class Submit { public static void main(String[] args) throws ExecutionException, InterruptedException { Runnable runnable = new Runnable() { public void run() { System.out.println("This is ThreadPoolExetor#submit(Runnable runnable) method."); } }; ExecutorService executor = Executors.newSingleThreadExecutor(); Future future = executor.submit(runnable); System.out.println(future.get()); } }
透過上面的實例可以看到在呼叫submit(Runnable runnable)的時候是不需要其定義型別的,也就是說雖然在ExecutorService中對其定義的是泛型方法,而在AbstractExecutorService中則不是泛型方法,因為它沒有回傳值。 (有關Object、T、?這三者的區別,可參考《Java中的Object、T(泛型)、?區別》)。
從上面的原始碼可以看到,這三者方法幾乎是一樣的,關鍵就在於:
RunnableFuture<T> ftask = newTaskFor(task); execute(ftask);
它是如何將一個任務作為參數傳遞給了newTaskFor,然後呼叫execute方法,最後再回傳ftask的呢?
//AbstractExecutorService#newTaskFor protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) { return new FutureTask<T>(callable); } protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) { return new FutureTask<T>(runnable, value); }
看來是回傳了一個FutureTask實例,FutureTask實作了Future和Runnable介面。 Future介面是Java執行緒Future模式的實現,可用用來非同步運算,實作Runnable介面表示可以作為一個執行緒執行。 FutureTask實作了這兩個介面意味著它代表非同步計算的結果,同時可以作為一個執行緒交給Executor來執行。有關FutureTask放到下章來單獨解析。所以本文對於執行緒池ThreadPoolExecutor執行緒池的submit方法解析並不完整,必須先了解Java執行緒的Future模式-《老生常談Java中的Future模式》。
以上是JAVA中ThreadPoolExecutor執行緒池的submit方法詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

熱門話題

Java 8引入了Stream API,提供了一種強大且表達力豐富的處理數據集合的方式。然而,使用Stream時,一個常見問題是:如何從forEach操作中中斷或返回? 傳統循環允許提前中斷或返回,但Stream的forEach方法並不直接支持這種方式。本文將解釋原因,並探討在Stream處理系統中實現提前終止的替代方法。 延伸閱讀: Java Stream API改進 理解Stream forEach forEach方法是一個終端操作,它對Stream中的每個元素執行一個操作。它的設計意圖是處

Java是熱門程式語言,適合初學者和經驗豐富的開發者學習。本教學從基礎概念出發,逐步深入解說進階主題。安裝Java開發工具包後,可透過建立簡單的「Hello,World!」程式來實踐程式設計。理解程式碼後,使用命令提示字元編譯並執行程序,控制台上將輸出「Hello,World!」。學習Java開啟了程式設計之旅,隨著掌握程度加深,可創建更複雜的應用程式。
