文章目录

  • 一、创建任务
  • 二、执行任务
    • 1、创建ExecutorService
    • 2、将任务添加到线程去执行
  • 三、关闭执行服务对象
  • 四、获取任务的执行的返回值
  • 五、ExecutorService的execute和submit方法区别,以及submit使用的具体Demo

在Java5之后,并发线程这块发生了根本的变化,最重要的莫过于新的启动、调度、管理线程的一大堆API了。在Java5以后,通过Executor来启动线程比用Thread的start()更好。在新特征中,可以很容易控制线程的启动、执行和关闭过程,还可以很容易使用线程池的特性。

一、创建任务

任务就是一个实现了Runnable接口的类。
创建的时候实run方法即可。

二、执行任务

通过java.util.concurrent.ExecutorService接口对象来执行任务该接口对象通过工具类java.util.concurrent.Executors的静态方法来创建

Executors此包中所定义的 Executor、ExecutorService、ScheduledExecutorService、ThreadFactory 和 Callable 类的工厂和实用方法。

ExecutorService提供了管理终止的方法,以及可为跟踪一个或多个异步任务执行状况而生成 Future 的方法。 可以关闭 ExecutorService,这将导致其停止接受新任务。关闭后,执行程序将最后终止,这时没有任务在执行,也没有任务在等待执行,并且无法提交新任务。
executorService.execute(new TestRunnable());

1、创建ExecutorService

通过工具类java.util.concurrent.Executors的静态方法来创建。
Executors此包中所定义的 Executor、ExecutorService、ScheduledExecutorService、ThreadFactory 和 Callable 类的工厂和实用方法。

比如,创建一个ExecutorService的实例,ExecutorService实际上是一个线程池的管理工具:

        ExecutorService executorService = Executors.newCachedThreadPool();ExecutorService executorService = Executors.newFixedThreadPool(3);ExecutorService executorService = Executors.newSingleThreadExecutor();

2、将任务添加到线程去执行

当将一个任务添加到线程池中的时候,线程池会为每个任务创建一个线程,该线程会在之后的某个时刻自动执行。

三、关闭执行服务对象

executorService.shutdown();

四、获取任务的执行的返回值

在Java5之后,任务分两类:

  • 一类是实现了Runnable接口的类
  • 一类是实现了Callable接口的类。

两者都可以被ExecutorService执行,但是Runnable任务没有返回值,而Callable任务有返回值。并且Callable的call()方法只能通过ExecutorService的( task) 方法来执行,并且返回一个 ,是表示任务等待完成的 Future。

public interface Callable<V>
返回结果并且可能抛出异常的任务。实现者定义了一个不带任何参数的叫做 call 的方法。
Callable 接口类似于,两者都是为那些其实例可能被另一个线程执行的类设计的。但是 Runnable 不会返回结果,并且无法抛出经过检查的异常。

类包含一些从其他普通形式转换成 Callable 类的实用方法。

Callable中的call()方法类似Runnable的run()方法,就是前者有返回值,后者没有:

  • 当将一个Callable的对象传递给ExecutorService的submit方法,则该call方法自动在一个线程上执行,并且会返回执行结果Future对象。

  • 同样,将Runnable的对象传递给ExecutorService的submit方法,则该run方法自动在一个线程上执行,并且会返回执行结果Future对象,但是在该Future对象上调用get方法,将返回null

五、ExecutorService的execute和submit方法区别,以及submit使用的具体Demo

1、接收的参数不一样

2、submit有返回值,而execute没有

Method submit extends base method Executor.execute by creating and returning a Future that can be used to cancel execution and/or wait for completion.

用到返回值的例子,比如说我有很多个做validation的task,我希望所有的task执行完,然后每个task告诉我它的执行结果,是成功还是失败,如果是失败,原因是什么。然后我就可以把所有失败的原因综合起来发给调用者。

个人觉得cancel execution这个用处不大,很少有需要去取消执行的。

而最大的用处应该是第二点。

3、submit方便Exception处理

There is a difference when looking at exception handling. If your tasks throws an exception and if it was submitted with execute this exception will Go to the uncaught exception handler (when you don’t have provided one explicitly, the default one will just print the stack trace to System.err). If you submitted the task with submit any thrown exception, checked or not, is then part of the task’s return status. For a task that was submitted with submit and that terminates with an exception, the Future.get will rethrow this exception, wrapped in an ExecutionException.

意思就是如果你在你的task里会抛出checked或者unchecked exception,而你又希望外面的调用者能够感知这些exception并做出及时的处理,那么就需要用到submit,通过捕获Future.get抛出的异常。

比如说,我有很多更新各种数据的task,我希望如果其中一个task失败,其它的task就不需要执行了。那我就需要catch Future.get抛出的异常,然后终止其它task的执行,代码如下:

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;public class ExecutorServiceTest {public static void main(String[] args) {ExecutorService executorService = Executors.newCachedThreadPool();List<Future<String>> resultList = new ArrayList<Future<String>>();// 创建10个任务并执行for (int i = 0; i < 10; i++) {// 使用ExecutorService执行Callable类型的任务,并将结果保存在future变量中Future<String> future = executorService.submit(new TaskWithResult(i));// 将任务执行结果存储到List中resultList.add(future);}executorService.shutdown();// 遍历任务的结果for (Future<String> fs : resultList) {try {System.out.println(fs.get()); // 打印各个线程(任务)执行的结果} catch (InterruptedException e) {e.printStackTrace();} catch (ExecutionException e) {executorService.shutdownNow();e.printStackTrace();return;}}}
}class TaskWithResult implements Callable<String> {private int id;public TaskWithResult(int id) {this.id = id;}/*** 任务的具体过程,一旦任务传给ExecutorService的submit方法,则该方法自动在一个线程上执行。** @return* @throws Exception*/public String call() throws Exception {System.out.println("call()方法被自动调用,干活!!!             " + Thread.currentThread().getName());// 下面的判读是模拟一个抛出异常的操作,随机得到一个trueif (new Random().nextBoolean())throw new TaskException("Meet error in task." + Thread.currentThread().getName());// 一个模拟耗时的操作for (int i = 999999999; i > 0; i--);return "call()方法被自动调用,任务的结果是:" + id + "    " + Thread.currentThread().getName();}
}class TaskException extends Exception {public TaskException(String message) {super(message);}
}

一种可能的执行结果:

call()方法被自动调用,干活!!!             pool-1-thread-4
call()方法被自动调用,干活!!!             pool-1-thread-2
call()方法被自动调用,干活!!!             pool-1-thread-1
call()方法被自动调用,干活!!!             pool-1-thread-5
call()方法被自动调用,干活!!!             pool-1-thread-3
call()方法被自动调用,干活!!!             pool-1-thread-7
call()方法被自动调用,干活!!!             pool-1-thread-8
call()方法被自动调用,干活!!!             pool-1-thread-4
call()方法被自动调用,干活!!!             pool-1-thread-6
call()方法被自动调用,干活!!!             pool-1-thread-9
call()方法被自动调用,任务的结果是:0    pool-1-thread-1
call()方法被自动调用,任务的结果是:1    pool-1-thread-2
call()方法被自动调用,任务的结果是:2    pool-1-thread-3
java.util.concurrent.ExecutionException: TaskException: Meet error in task.pool-1-thread-4at java.util.concurrent.FutureTask.report(FutureTask.java:122)at java.util.concurrent.FutureTask.get(FutureTask.java:192)at ExecutorServiceTest.main(ExecutorServiceTest.java:27)
Caused by: TaskException: Meet error in task.pool-1-thread-4at TaskWithResult.call(ExecutorServiceTest.java:56)at TaskWithResult.call(ExecutorServiceTest.java:1)at java.util.concurrent.FutureTask.run(FutureTask.java:266)at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)at java.lang.Thread.run(Thread.java:748)

分析:10个任务,只有3条打印输出结果了,而某个线程抛出异常后,触发通知,让整个执行器关闭,那么剩余的未完成任务也提前终止了

参考:
《ExecutorService的submit方法使用》

【线程 锁】ExecutorService的submit方法使用相关推荐

  1. ExecutorService的submit()方法

    ExecutorService总共有三个submit方法: Future<?> submit(Runnable task); <T> Future<T> submi ...

  2. 线程池ExecutorService中submit和execute区别

    1.execute是接口Executor的方法 ,submit是Executor子接口ExecutorService的方法(ExecutorService接口继承了Executor接口,Executo ...

  3. C# 关于线程锁lock的使用方法

    在多线程编程中,可能会有许多线程并发的执行一段代码(代码块A),以提高执行效率.在某些情况下,我们希望A中的代码块(B)同步的执行,即同一时刻只有一个线程执行代码块B,这就需要用到锁(lock).lo ...

  4. ExecutorService中submit和execute的区别转

    在Java5之后,并发线程这块发生了根本的变化,最重要的莫过于新的启动.调度.管理线程的一大堆API了.在Java5以后,通过Executor来启动线程比用Thread的start()更好.在新特征中 ...

  5. ExecutorService中submit和execute的区别(转)

    在Java5之后,并发线程这块发生了根本的变化,最重要的莫过于新的启动.调度.管理线程的一大堆API了.在Java5以后,通过Executor来启动线程比用Thread的start()更好.在新特征中 ...

  6. Java线程池ExecutorService

    开篇前,我们先来看看不使用线程池的情况: new Thread的弊端 执行一个异步任务你还只是如下new Thread吗? new Thread(new Runnable() {@Overridepu ...

  7. Java内置线程池ExecutorService介绍及商品秒杀案例

    第一.ExecutorService接口是java内置的线程池接口,通过学习接口中的方法,可以快速的掌握java内置线程池的基本使用 常用方法: void shutdown() 启动一次顺序关闭,执行 ...

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

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

  9. 13.ThreadPoolExecutor线程池之submit方法

    jdk1.7.0_79  在上一篇<ThreadPoolExecutor线程池原理及其execute方法>中提到了线程池ThreadPoolExecutor的原理以及它的execute方法 ...

  10. Java线程池ExecutorService中重要的方法

    ExecutorService 介绍 ExecutorService是java线程池定义的一个接口,它在java.util.concurrent包中,在这个接口中定义了和后台任务执行相关的方法. Ja ...

最新文章

  1. python网络爬虫---selenium的使用
  2. commonjs是什么_第一步:面试官让我解释什么是Common.js和ES6模块化
  3. 面试官问我JVM内存结构,我真的是
  4. Spark-shell提示找不到路径
  5. Android远程服务与本地服务的特点以及功能差异
  6. activemq linux教程,Linux及Windows下ActiveMQ下载与安装教程
  7. Lync Server 2010企业版系列PART5:生成拓扑
  8. php生成图片文件流,php 如何把图片转化为字节流存储到数据库?
  9. sql表格模型获取记录内容_SQL Server和BI –如何使用Excel记录表格模型
  10. python中datetime函数怎么获得当年年份_Python 日期和时间函数使用指南
  11. 获取TextView每行的内容 (涉及getLineCount为0,getLineEnd问题)
  12. php连接云数据库服务器,服务器使用PHP连接sqlserver数据库
  13. 黑马品优购项目的总结-首页
  14. PHP学习笔记:利用gd库给图片打图片水印
  15. 微信小程序 选择器 picker ;demo大全附效果图
  16. php disable hugepage,禁用Transparent Huge Pages
  17. 基于51单片机的扫地小车,扫地机器人设计。 有原理图,程序代码,原文
  18. Openstack 简单梳理,(自用 慎点)
  19. 深度学习21天——卷积神经网络(CNN):实现mnist手写数字识别(第1天)
  20. 宜信智能监控平台建设实践|分享实录

热门文章

  1. 计算机缓存设置方法,如何清除电脑缓存?清除电脑缓存方法介绍
  2. 窦唯与女儿【节选】揭秘男星与女儿之间的奇闻
  3. java星星闪烁代码_jQuery实现仿QQ头像闪烁效果的文字闪动提示代码
  4. 禁止收录与跟踪-- Robots 文件优化和Nofollow 优化
  5. Xiangqi UVA - 1589
  6. 快速清除系统中的木马病毒
  7. 第7关:可以重复进行汇率兑换计算的小程序
  8. java输入无名粉_05·无名粉店(上)
  9. lingo纳什均衡代码_传统的战略式博弈求解纳什均衡方法——虚拟博弈(Fictitious Play)讲解及其代码...
  10. Ubuntu设置自动登录