简单谈谈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 { ...Future submit(Callable task); Future submit(Runnable task, T result); Future submit(Runnable task); ... }
而在其子类AbstractExecutorService实现了submit方法。
//AbstractExecutorService public abstract class AbstractExecutorService implements ExecutorService { ... publicFuture submit(Callable task) { if (task == null) throw new NullPointerException(); RunnableFuture ftask = newTaskFor(task); execute(ftask); return ftask; } public Future submit(Runnable task, T result) { if (task == null) throw new NullPointerException(); RunnableFuture ftask = newTaskFor(task); execute(ftask); return ftask; } public Future<?> submit(Runnable task) { if (task == null) throw new NullPointerExeption(); RunnableFuture 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(Callabletask) * Created by yulinfeng on 6/17/17. */ public class Sumit1 { public static void main(String[] args) throws ExecutionException, InterruptedException { Callable callable = new Callable () { public String call() throws Exception { System.out.println("This is ThreadPoolExetor#submit(Callable task) method."); return "result"; } }; ExecutorService executor = Executors.newSingleThreadExecutor(); Future 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 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(泛型)、?区别》)。
从上面的源码可以看到,这三者方法几乎是一样的,关键就在于:
RunnableFutureftask = newTaskFor(task); execute(ftask);
它是如何将一个任务作为参数传递给了newTaskFor,然后调用execute方法,最后进而返回ftask的呢?
//AbstractExecutorService#newTaskFor protectedRunnableFuture newTaskFor(Callable callable) { return new FutureTask (callable); } protected RunnableFuture newTaskFor(Runnable runnable, T value) { return new FutureTask (runnable, value); }
看来是返回了一个FutureTask实例,FutureTask实现了Future和Runnable接口。Future接口是Java线程Future模式的实现,可用用来异步计算,实现Runnable接口表示可以作为一个线程执行。FutureTask实现了这两个接口意味着它代表异步计算的结果,同时可以作为一个线程交给Executor来执行。有关FutureTask放到下章来单独解析。所以本文对于线程池ThreadPoolExecutor线程池的submit方法解析并不完整,必须得了解Java线程的Future模式——《老生常谈Java中的Future模式》。
以上这篇简单谈谈ThreadPoolExecutor线程池之submit方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持创新互联。
当前文章:简单谈谈ThreadPoolExecutor线程池之submit方法
转载来源:http://ybzwz.com/article/pehpch.html