JDK8 并发包学习 Executor/ExecutorService(一)

本文介绍jdk8并发包中的Executor/ExecutorService这两个接口。

Executor接口

概述

该类提供一个提交任务的方法,提交的任务可以在提交程序本线程运行,也可以在不同的线程运行,也可以在一个线程池中的线程运行,全看如何使用。

However, the {@code Executor} interface does not strictly

require that execution be asynchronous. In the simplest case, an executor can run the submitted task immediately in the caller’s thread

然而,该接口并没有严格规定提交的任务是异步执行的,最简单的情况,提交的任务可以直接由任务的caller thread执行。

More typically, tasks are executed in some thread other

than the caller’s thread. The executor below spawns a new thread for each task

更典型的情况是提交的任务并不是由caller thread执行,而是创建了新的线程去执行,比如线程池。

execute方法

该接口提供一个方法:

void execute(Runnable command);

该方法的作用是提交一个任务,这个任务在未来的某一时刻会被执行,该任务可能被新的线程执行,可能被线程池中的线程执行,也有可能就被提交者本身的线程执行。

ExecutorService接口

概述

ExecutorService继承于Executor,它提供一些可以管理任务的执行、取消、结束的方法。

shutdown方法

void shutdown();

shutdown方法调用之后,马上拒绝接收新的任务,但是之前已经提交的任务会继续执行。

shutdownNow方法

List<Runnable> shutdownNow();

该函数调用之后,马上拒绝接收新的任务,并且会尝试结束当前正在执行的任务,直到所有任务真正结束为止,并且会返回等待执行的任务的列表。

isShutdown方法

boolean isShutdown();

该函数判断service是否已经被shutdown,如果调用过shutdown函数,则返回true,否则返回false。

isTerminated方法

boolean isTerminated();

该函数判断service中得所有任务是否已经全部执行完毕,并且应该注意的是:如果没有调用过shutdown函数或者shutdownNow函数,该函数的返回值不可能为true。

awaitTermination方法

boolean awaitTermination(long timeout, TimeUnit unit)
        throws InterruptedException;

该函数会一直阻塞直到所有的任务已经被执行或者等待时间到。

submit方法

<T> Future<T> submit(Callable<T> task);
<T> Future<T> submit(Runnable task, T result);
Future<?> submit(Runnable task);

这些函数都是向service提交一个任务,并且返回一个Futrue对象,用于追踪任务的执行情况。区别在于第一个函数在任务执行完毕之后Futrue.get()将会返回任务执行的结果,第二个函数在任务执行完毕之后Future.get()将会返回给定的result结果,而第三个函数在任务执行完毕之后Future.get()将会返回null。

invokeAll方法

<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) throws InterruptedException;

<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,long timeout, TimeUnit unit)
throws InterruptedException;

这些方法比较好理解,就是执行任务列表中的所有任务,并返回与每个任务对应的Futue。也就是说,任务彼此之间不会相互影响,可以通过future跟踪每一个任务的执行情况,比如是否被取消,是正常完成,还是异常完成,这主要使用Future类提供的API。invokeAll是一个阻塞方法,会等待任务列表中的所有任务都执行完成。不管任务是正常完成,还是异常终止,Future.isDone()始终返回true。通过

Future.isCanceled()可以判断任务是否在执行的过程中被取消。通过Future.get()可以获取任务的返回结果,或者是任务在执行中抛出的异常。

invokeAny方法

<T> T invokeAny(Collection<? extends Callable<T>> tasks)
        throws InterruptedException, ExecutionException;

<T> T invokeAny(Collection<? extends Callable<T>> tasks,
      long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException;

上面的函数执行给定的一系列任务,当某一个任务成功执行(没有抛出异常)时,返回该任务对应的Future对象,其他所有未被执行的任务都将取消。如果执行过程中修改了tasks列表,则返回的结果是不确定的。第二个函数带有超时时间。此外还应该注意:

  • 一旦有1个任务正常完成(执行过程中没有抛异常),线程池会终止>其他未完成的任务 。
  • 如果提交的任务列表中,没有1个正常完成的任务,那么调用invokeAny会抛异常,究竟抛的是哪儿个任务的异常,无关紧要
  • invokeAny()和任务的提交顺序无关,只是返回最早正常执行完成的任务
  • 如果在超时之前,所有任务已经都是异常终止,那就没有必要在等下去了;如果超时之后,仍然有正在运行或等待运行的任务,那么会抛出TimeoutException。

版权声明:本文为博主原创文章,转载请注明出处,并附上链接。

时间: 2024-11-05 13:42:39

JDK8 并发包学习 Executor/ExecutorService(一)的相关文章

Executor, ExecutorService 和 Executors 间的不同

一.Java 线程池 Java通过Executors提供四种线程池,分别为:1.newCachedThreadPool: 创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程.(线程最大并发数不可控制)2.newFixedThreadPool: 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待.3.newScheduledThreadPool:创建一个定长线程池,支持定时及周期性任务执行.4.newSingleThreadExecutor

java 并发包学习

java 并发包学习 1: ConcurrentHashMap:  ConcurrentHashMap : 线程安全效率高于hashTable, jdk1.7中使用的是分段锁, 将数据分成多个hashTable,避免了多个线程竞争同一把锁,导致效率低下 在JDK1.7和JDK1.8中的区别: 在JDK1.8主要设计上的改进有以下几点: 1.不采用segment而采用node,锁住node来实现减小锁粒度. 2.设计了MOVED状态 当resize的中过程中 线程2还在put数据,线程2会帮助re

Java再学习——Executor,ExecutorService,ScheduledExecutorService与Executors

1,Executor.ExecutorService和ScheduledExecutorService,它们都是接口,它们的关系是ScheduledExecutorService继承ExecutorService而ExecutorService 又继承Executor. 这些只要点开源码就能看得到. 2,对于Executor接口,它只有一个方法void execute(Runnable command);而其后的ExecutorService和ScheduledExecutorService就各

[Java并发包学习七]解密ThreadLocal

概述 相信读者在网上也看了很多关于ThreadLocal的资料,很多博客都这样说:ThreadLocal为解决多线程程序的并发问题提供了一种新的思路:ThreadLocal的目的是为了解决多线程访问资源时的共享问题.如果你也这样认为的,那现在给你10秒钟,清空之前对ThreadLocal的错误的认知! 看看JDK中的源码是怎么写的: This class provides thread-local variables. These variables differ from their norm

java并发编程框架 Executor ExecutorService invokeall

首先介绍两个重要的接口,Executor和ExecutorService,定义如下: Java代码   public interface Executor { void execute(Runnable command); } Java代码   public interface ExecutorService extends Executor { //不再接受新任务,待所有任务执行完毕后关闭ExecutorService void shutdown(); //不再接受新任务,直接关闭Execut

Executor ExecutorService Executors

Executor public interface Executor { void execute(Runnable command); } ExecutorService ExecutorService是一个接口,继承了Executor接口,定义了一些生命周期的方法 public interface ExecutorService extends Executor { //顺次地关闭ExecutorService,停止接收新的任务,等待所有已经提交的任务执行完毕之后,关闭ExecutorSer

java Executor, ExecutorService, Executors 有什么不同

Executor 是一个接口,只定义了一个方法, 可以接收Runnable实例,用来执行一个实现Runnable接口的任务. void execute(Runnable command); ExecutorService 也是一个接口,继承自Executor,并增加了一些方法,用的比较广泛,提供了一些生命周期的方法.shutdown,还有submit方法返回值是future. ExecutorService就是为了解决执行服务的生命周期问题的. ExecutorService的生命周期有3种状态

Java并发包学习一 ThreadFactory介绍

ThreadFactory翻译过来是线程工厂,顾名思义,就是用来创建线程的,它用到了工厂模式的思想.它通常和线程池一起使用,主要用来控制创建新线程时的一些行为,比如设置线程的优先级,名字等等.它是一个接口,接口中只有一个方法: /* * * * * * * Written by Doug Lea with assistance from members of JCP JSR-166 * Expert Group and released to the public domain, as expl

并发包学习之-atomic包

一,模拟并发代码: 线程不安全的代码 //并发模拟代码 public class CountExample { //请求总数 public static int clientTotal = 5000; //同时并发执行的线程数 public static int threadTotal = 200; //全局变量 public static int count = 0; public static void main(String[] args) { ExecutorService execut