博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
13.ThreadPoolExecutor线程池之submit方法
阅读量:5950 次
发布时间:2019-06-19

本文共 5466 字,大约阅读时间需要 18 分钟。

jdk1.7.0_79 

  在上一篇中提到了线程池ThreadPoolExecutor的原理以及它的execute方法。本文解析ThreadPoolExecutor#submit。

  对于一个任务的执行有时我们不需要它返回结果,但是有我们需要它的返回执行结果。对于线程来讲,如果不需要它返回结果则实现Runnable,而如果需要执行结果的话则可以实现Callable。在线程池同样execute提供一个不需要返回结果的任务执行,而对于需要结果返回的则可调用其submit方法。

  回顾ThreadPoolExecutor的继承关系。

  

  在Executor接口中只定义了execute方法,而submit方法则是在ExecutorService接口中定义的。

  

//ExecutorServicepublic interface ExecutorService extends Executor {  ...  
Future
submit(Callable
task);  
Future
submit(Runnable task, T result);  
Future
submit(Runnable task);  ...}

  而在其子类AbstractExecutorService实现了submit方法。

//AbstractExecutorServicepublic abstract class AbstractExecutorService implements ExecutorService {  ...  public 
Future
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<T> task)能获取到它的返回值,submit(Runnable task, T result)能通过传入的载体result间接获得线程的返回值或者准确来说交给线程处理一下,而最后一个方法submit(Runnable task)则是没有返回值的,就算获取它的返回值也是null。

  下面给出3个例子,来感受下submit方法。

  submit(Callable<T> task)

package com.threadpoolexecutor;import java.util.concurrent.*;/** * ThreadPoolExecutor#sumit(Callable
task) * 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、?这三者的区别,可参考)。

  从上面的源码可以看到,这三者方法几乎是一样的,关键就在于:

RunnableFuture
ftask = newTaskFor(task);execute(ftask);

  它是如何将一个任务作为参数传递给了newTaskFor,然后调用execute方法,最后进而返回ftask的呢?

//AbstractExecutorService#newTaskForprotected 
RunnableFuture
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模式——。

转载地址:http://ceixx.baihongyu.com/

你可能感兴趣的文章
正则表达式验证身份证格式是否正确
查看>>
Firebird(全功能的,免维护的数据库,能够管理多个独立的数据库) V2.1.3 英文特别版...
查看>>
xml格式文件解析
查看>>
ios百度地图-路径规划
查看>>
Python高效编程技巧
查看>>
配置Eclipse使用maven构建项目默认JDK为1.8
查看>>
jsp内置对象以及jsp动作
查看>>
Struts上路_09-数据类型转换
查看>>
CMake与动态链接库(dll, so, dylib)
查看>>
myeclipse(eclipse)乱码处理
查看>>
SpringBoot 过滤器, 拦截器, 监听器 对比及使用场景
查看>>
数据库索引探索
查看>>
struts2使用json需要注意的问题
查看>>
gitlab runner 优化
查看>>
快速添加百度网盘文件到Aria2 猴油脚本
查看>>
mac 无法登录mysql的解决办法
查看>>
Shiro权限判断异常之命名导致的subject.isPermitted 异常
查看>>
Hello world travels in cpp - 字符串(2)
查看>>
struts2自定义拦截器
查看>>
Eclipse安装adt插件后之后看不到andorid manger
查看>>