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<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<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模式——《14.Java中的Future模式》。

13.ThreadPoolExecutor线程池之submit方法相关推荐

  1. Java Executor源码解析(3)—ThreadPoolExecutor线程池execute核心方法源码【一万字】

    基于JDK1.8详细介绍了ThreadPoolExecutor线程池的execute方法源码! 上一篇文章中,我们介绍了:Java Executor源码解析(2)-ThreadPoolExecutor ...

  2. 线程池中submit()方法与execute()方法的区别

    execute()方法实际上是Executor中声明的方法,在ThreadPoolExecutor进行了具体的实现,这个方法是ThreadPoolExecutor的核心方法,通过这个方法可以向线程池提 ...

  3. ThreadPoolExecutor线程池使用及参数详解

    先贴一段实际应用代码,应用场景是一个基于http请求拦截的用户行为分析数据录入片段: package com.howbuy.coop.interceptor;import java.sql.Times ...

  4. ThreadPoolExecutor 线程池异常消失之刨根问底

    一.情景复现 昨天,公司一个同事,急急忙忙的跑过来找我,说他的项目,出现了一个非常诡异的BUG,不知道什么情况? 同事:我用五个线程计算学生各个科目的成绩,最后汇总,本地都是正常的,但是一到测试环境就 ...

  5. ThreadPoolExecutor线程池原理

    ThreadPoolExecutor线程池原理 线程池原理 1. 线程池的简单介绍 1.1 线程池是什么 1.2 线程池解决的核心问题是什么 2. 线程池的实现原理 2.1 线程池的执行流程 2.2 ...

  6. Java线程池的使用方法

    前言 多线程的异步执行方式,虽然能够最大限度发挥多核计算机的计算能力,但是如果不加控制,反而会对系统造成负担.线程本身也要占用内存空间,大量的线程会占用内存资源并且可能会导致Out of Memory ...

  7. ThreadPoolExecutor线程池,shutdown和shutdownNow关闭线程池方式对比,以及确保线程池能够彻底关闭的一种方式

    1. ThreadPoolExecutor线程池 1.1 创建线程池,构造方法的几个参数说明及创建如下. 1.2 shutdown方式关闭线程池 a. 空闲且能interrupt表示该线程处于阻塞等待 ...

  8. 优雅的自定义 ThreadPoolExecutor 线程池

    概述 java 中经常需要用到多线程来处理一些业务,非常不建议单纯使用继承Thread或者实现Runnable接口的方式来创建线程,那样势必有创建及销毁线程耗费资源.线程上下文切换问题.同时创建过多的 ...

  9. ThreadPoolExecutor线程池核心参数详解

    理解ThreadPoolExecutor线程池的corePoolSize.maximumPoolSize和poolSize 我们知道,受限于硬件.内存和性能,我们不可能无限制的创建任意数量的线程,因为 ...

最新文章

  1. 科室鄙视链最底端,居然是这类人
  2. Pandas批量删除dataframe列名中的后缀实战:使用rstrip函数批量删除列名中的后缀(suffix)、使用replace函数批量删除列名中的后缀(suffix)
  3. CCF-CSP 201712-2 游戏(C++实现)
  4. Java有序表查找:折半查找、二分查找、差值查找和斐波那契查找
  5. WPF遍历当前容器中某种控件的方法
  6. 了不起的华人女数学家们
  7. centos7+svn+mysql_Linux下安装SVN服务(CentOS7下)
  8. Logistic Regression逻辑回归的损失函数与梯度下降训练
  9. qt纯c++编程增加多线程支持库
  10. qt编写的android程序在android系统中运行,中文显示乱码的解决方法
  11. Linux中的nc测试端口是否开放
  12. Hadoop管理员的十个最佳实践(转)
  13. Tsys1.1使用经验(汇集中)
  14. JavaScript全套视频教程
  15. 中医大2020年7月网考计算机应用基础,2020年7月网络教育统考计算机应用基础模拟题试卷9...
  16. java button属性设置_java的JButton怎样设置内边距
  17. 积微——荀子《强国篇》,给每个职场人士推荐
  18. nginx负载均衡之一致性Hash方式
  19. 偷偷修复漏洞 苹果要求研究员噤声
  20. Linux 这些工具堪称神器!你用过哪个?

热门文章

  1. orton效果_如何使图片发光:Orton效果
  2. 1.1编写目的_1.目的
  3. 构建安全的Xml Web Service系列之如何察看SoapMessage
  4. PXC集群常见错误(一)
  5. 记录一次解决httpcline请求https报handshake_failure错误
  6. Linux 性能监控 : CPU 、Memory 、 IO 、Network
  7. Linux之tomcat日志管理
  8. Android两个注意事项.深入了解Intent和IntentFilter(两)
  9. 超级马里奥代码_任天堂的源码泄露,揭示超级马里奥的前世之生
  10. python线性回归算法简介_Python实现的简单线性回归算法实例分析