全网整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:400-708-3566

简单谈谈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<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模式——《老生常谈Java中的Future模式》。

以上这篇简单谈谈ThreadPoolExecutor线程池之submit方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持。


# 线程池submit  # Java线程池submit阻塞获取结果的实现原理详解  # 线程池中execute与submit的区别说明  # 线程池之exectue与submit的区别及说明  # 返回值  # 不需要  # 可以看到  # 实现了  # 子类  # 则是  # 而在  # 给了  # 给大家  # 作为一个  # 则可  # 这三  # 的是  # 是一个  # 也就是说  # 是在  # 会有  # 是有  # 老生常谈  # 它是 


相关文章: 如何通过多用户协作模板快速搭建高效企业网站?  建站OpenVZ教程与优化策略:配置指南与性能提升  如何通过云梦建站系统实现SEO快速优化?  微信小程序制作网站有哪些,微信小程序需要做网站吗?  如何在阿里云虚拟服务器快速搭建网站?  如何用PHP工具快速搭建高效网站?  建站主机如何安装配置?新手必看操作指南  焦点电影公司作品,电影焦点结局是什么?  如何优化Golang Web性能_Golang HTTP服务器性能提升方法  建站主机选择指南:服务器配置与SEO优化实战技巧  大同网页,大同瑞慈医院官网?  制作网站的网址是什么,请问后缀为.com和.com.cn还有.cn的这三种网站是分别是什么类型的网站?  C++用Dijkstra(迪杰斯特拉)算法求最短路径  C#如何在一个XML文件中查找并替换文本内容  如何快速搭建高效服务器建站系统?  如何快速查询网站的真实建站时间?  如何选择适配移动端的WAP自助建站平台?  如何在阿里云ECS服务器部署织梦CMS网站?  如何在香港免费服务器上快速搭建网站?  javascript中对象的定义、使用以及对象和原型链操作小结  建站之星如何快速更换网站模板?  php json中文编码为null的解决办法  高性价比服务器租赁——企业级配置与24小时运维服务  北京专业网站制作设计师招聘,北京白云观官方网站?  C++时间戳转换成日期时间的步骤和示例代码  外贸公司网站制作哪家好,maersk船公司官网?  C++ static_cast和dynamic_cast区别_C++静态转换与动态类型安全转换  如何快速生成ASP一键建站模板并优化安全性?  Android自定义listview布局实现上拉加载下拉刷新功能  官网网站制作腾讯审核要多久,联想路由器newifi官网  如何基于云服务器快速搭建网站及云盘系统?  ,巨量百应是干嘛的?  想学网站制作怎么学,建立一个网站要花费多少?  如何快速完成中国万网建站详细流程?  建站之星代理商如何保障技术支持与售后服务?  建站主机如何选?性能与价格怎样平衡?  网站专业制作公司有哪些,做一个公司网站要多少钱?  建站主机是什么?如何选择适合的建站主机?  c++怎么用jemalloc c++替换默认内存分配器【性能】  如何确认建站备案号应放置的具体位置?  寿县云建站:智能SEO优化与多行业模板快速上线指南  Android使用GridView实现日历的简单功能  ,有什么在线背英语单词效率比较高的网站?  云南网站制作公司有哪些,云南最好的招聘网站是哪个?  如何选择最佳自助建站系统?快速指南解析优劣  高配服务器限时抢购:企业级配置与回收服务一站式优惠方案  齐河建站公司:营销型网站建设与SEO优化双核驱动策略  如何配置IIS站点权限与局域网访问?  如何高效生成建站之星成品网站源码?  ,石家庄四十八中学官网? 

您的项目需求

*请认真填写需求信息,我们会在24小时内与您取得联系。