簡(jiǎn)單談?wù)凾hreadPoolExecutor線(xiàn)程池之submit方法
jdk1.7.0_79
在上一篇《ThreadPoolExecutor線(xiàn)程池原理及其execute方法》中提到了線(xiàn)程池ThreadPoolExecutor的原理以及它的execute方法。本文解析ThreadPoolExecutor#submit。
對(duì)于一個(gè)任務(wù)的執(zhí)行有時(shí)我們不需要它返回結(jié)果,但是有我們需要它的返回執(zhí)行結(jié)果。對(duì)于線(xiàn)程來(lái)講,如果不需要它返回結(jié)果則實(shí)現(xiàn)Runnable,而如果需要執(zhí)行結(jié)果的話(huà)則可以實(shí)現(xiàn)Callable。在線(xiàn)程池同樣execute提供一個(gè)不需要返回結(jié)果的任務(wù)執(zhí)行,而對(duì)于需要結(jié)果返回的則可調(diào)用其submit方法。
回顧ThreadPoolExecutor的繼承關(guān)系。
在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); ... }
而在其子類(lèi)AbstractExecutorService實(shí)現(xiàn)了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實(shí)現(xiàn)的submit方法實(shí)際上是一個(gè)模板方法,定義了submit方法的算法骨架,其execute交給了子類(lèi)。(可以看到在很多源碼中,模板方法模式被大量運(yùn)用,有關(guān)模板方法模式可參考《模板方法模式》)
盡管submit方法能提供線(xiàn)程執(zhí)行的返回值,但只有實(shí)現(xiàn)了Callable才會(huì)有返回值,而實(shí)現(xiàn)Runnable的線(xiàn)程則是沒(méi)有返回值的,也就是說(shuō)在上面的3個(gè)方法中,submit(Callable<T> task)能獲取到它的返回值,submit(Runnable task, T result)能通過(guò)傳入的載體result間接獲得線(xiàn)程的返回值或者準(zhǔn)確來(lái)說(shuō)交給線(xiàn)程處理一下,而最后一個(gè)方法submit(Runnable task)則是沒(méi)有返回值的,就算獲取它的返回值也是null。
下面給出3個(gè)例子,來(lái)感受下submit方法。
submit(Callable<T> task)
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()); } }
通過(guò)上面的實(shí)例可以看到在調(diào)用submit(Runnable runnable)的時(shí)候是不需要其定義類(lèi)型的,也就是說(shuō)雖然在ExecutorService中對(duì)其定義的是泛型方法,而在AbstractExecutorService中則不是泛型方法,因?yàn)樗鼪](méi)有返回值。(有關(guān)Object、T、?這三者的區(qū)別,可參考《Java中的Object、T(泛型)、?區(qū)別》)。
從上面的源碼可以看到,這三者方法幾乎是一樣的,關(guān)鍵就在于:
RunnableFuture<T> ftask = newTaskFor(task); execute(ftask);
它是如何將一個(gè)任務(wù)作為參數(shù)傳遞給了newTaskFor,然后調(diào)用execute方法,最后進(jìn)而返回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); }
看來(lái)是返回了一個(gè)FutureTask實(shí)例,F(xiàn)utureTask實(shí)現(xiàn)了Future和Runnable接口。Future接口是Java線(xiàn)程Future模式的實(shí)現(xiàn),可用用來(lái)異步計(jì)算,實(shí)現(xiàn)Runnable接口表示可以作為一個(gè)線(xiàn)程執(zhí)行。FutureTask實(shí)現(xiàn)了這兩個(gè)接口意味著它代表異步計(jì)算的結(jié)果,同時(shí)可以作為一個(gè)線(xiàn)程交給Executor來(lái)執(zhí)行。有關(guān)FutureTask放到下章來(lái)單獨(dú)解析。所以本文對(duì)于線(xiàn)程池ThreadPoolExecutor線(xiàn)程池的submit方法解析并不完整,必須得了解Java線(xiàn)程的Future模式——《老生常談Java中的Future模式》。
以上這篇簡(jiǎn)單談?wù)凾hreadPoolExecutor線(xiàn)程池之submit方法就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Java多線(xiàn)程異步調(diào)用性能調(diào)優(yōu)方法詳解
這篇文章主要為大家詳細(xì)介紹了Java多線(xiàn)程異步調(diào)用性能調(diào)優(yōu),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助2022-03-03Java數(shù)組聲明、創(chuàng)建、初始化基礎(chǔ)
本文講述了Java數(shù)組的幾個(gè)相關(guān)的方面,講述了對(duì)Java數(shù)組的聲明、創(chuàng)建和初始化,并給出其對(duì)應(yīng)的代碼2012-12-12java 中DH的方式實(shí)現(xiàn)非對(duì)稱(chēng)加密的實(shí)例
這篇文章主要介紹了java 中DH的方式實(shí)現(xiàn)非對(duì)稱(chēng)加密的實(shí)例的相關(guān)資料,這里提供實(shí)現(xiàn)簡(jiǎn)單實(shí)例,需要的朋友可以參考下2017-08-08