java.util.concurrent.ExecutorService 接口 源码

线程池相关

源码:

package java.util.concurrent;

import java.util.List;
import java.util.Collection;

public interface ExecutorService extends Executor {
    //启动一次顺序关闭,执行以前提交的任务,但不接受新任务
    void shutdown();

    //试图停止所有正在执行的活动任务,暂停处理正在等待的任务,并返回等待执行的任务列表
    List<Runnable> shutdownNow();

    //如果此执行程序已关闭,则返回 true
    boolean isShutdown();

    //如果关闭后所有任务都已完成,则返回 true
    boolean isTerminated();

    //阻塞当前线程:直到所有任务执行完毕、等待超时或者当前线程中断,才会返回
    boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException;

    //提交一个返回值的任务用于执行,返回一个表示任务的未决结果的 Future
    <T> Future<T> submit(Callable<T> task);

    //提交一个 Runnable 任务用于执行,并返回一个表示该任务的 Future
    Future<?> submit(Runnable task);

    //提交一个 Runnable 任务用于执行,并返回一个表示该任务的 Future
    <T> Future<T> submit(Runnable task, T result);

    //执行给定的任务,当所有任务完成时,返回保持任务状态和结果的 Future 列表
    <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) throws InterruptedException;

    // 执行给定的任务,当所有任务完成或超时期满时(无论哪个首先发生),返回保持任务状态和结果的 Future 列表
    <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,long timeout, TimeUnit unit) throws InterruptedException;

    //执行给定的任务,如果某个任务已成功完成(也就是未抛出异常),则返回其结果
    <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;
}

接口 ExecutorService

父接口:

    Executor

已知子接口:

    ScheduledExecutorService

已知实现类:

    AbstractExecutorServiceScheduledThreadPoolExecutorThreadPoolExecutor

    提供两个方法来关闭 ExecutorService:

    shutdown() 方法在终止前允许执行以前提交的任务;无法提交新任务。

    shutdownNow() 方法阻止等待任务启动并试图停止当前正在执行的任务。没有任务在等待执行,并且无法提交新任务,执行中的任务将会收到中断信号。

    从父接口,继承得到的 execute(Runnable command) 方法,只能执行Runnable类型的线程,而且还不能得到返回值。在ExecutorService 中 submit() 通过返回一个可获取返回值的 Future,不仅支持了执行Runnable类型的线程,也支持了Callable的线程执行。

扫描二维码关注公众号,回复: 4250491 查看本文章

    invokeAny() 和 invokeAll() 是批量执行的最常用形式,它们执行任务 collection,然后等待至少一个,或全部任务完成(可使用 ExecutorCompletionService 类来编写这些方法的自定义变体)。

 Executors 类提供了用于此包中所提供的执行程序服务的工厂方法。

 

shutdown

void shutdown()

    启动一次顺序关闭,执行以前提交的任务,但不接受新任务。如果已经关闭,则调用没有其他作用。

    抛出:

    SecurityException - 如果安全管理器存在并且关闭,此 ExecutorService 可能操作某些不允许调用者修改的线程(因为它没有保持 RuntimePermission ("modifyThread")),或者安全管理器的 checkAccess 方法拒绝访问。

shutdownNow

List<Runnable> shutdownNow()

    试图停止所有正在执行的活动任务,暂停处理正在等待的任务,并返回等待执行的任务列表。

    无法保证能够停止正在处理的活动执行任务,但是会尽力尝试。例如,通过 Thread.interrupt() 来取消典型的实现,所以无法响应中断的任务可能将永远无法终止。

    返回:

        从未开始执行的任务的列表

    抛出:

    SecurityException - 如果安全管理器存在并且关闭,此 ExecutorService 可能操作某些不允许调用者修改的线程(因为它没有保持 RuntimePermission ("modifyThread")),或者安全管理器的 checkAccess 方法拒绝访问。

isShutdown

boolean isShutdown()

    如果此执行程序已关闭,则返回 true。

    返回:

        如果此执行程序已关闭,则返回 true

isTerminated

boolean isTerminated()

    如果关闭后所有任务都已完成,则返回 true。注意,除非首先调用 shutdown 或 shutdownNow,否则 isTerminated 永不为 true。

    返回:

        如果关闭后所有任务都已完成,则返回 true

awaitTermination

boolean awaitTermination(long timeout,TimeUnit unit) throws InterruptedException

    阻塞当前线程:直到所有任务执行完毕、等待超时或者当前线程中断,才会返回。

    一般在调用shutdown()方法后调用,用来检测 timeout 时间后线程池是否关闭。

    参数:

    timeout - 最长等待时间

    unit - timeout 参数的时间单位

    返回:

        如果此执行程序终止,则返回 true;如果终止前超时期满,则返回 false

    抛出:

    InterruptedException - 如果等待时发生中断

submit

<T> Future<T> submit(Callable<T> task)

    提交一个返回值的任务用于执行,返回一个表示任务的未决结果的 Future。该 Future 的 get 方法在成功完成时将会返回该任务的结果。

    如果想立即阻塞任务的等待,则可以使用 result = exec.submit(aCallable).get(); 形式的构造。

    注:Executors 类包括了一组方法,可以转换某些其他常见的类似于闭包的对象,例如,将 PrivilegedAction 转换为 Callable 形式,这样就可以提交它们了。

    参数:

    task - 要提交的任务

    返回:

        表示任务等待完成的 Future

    抛出:

    RejectedExecutionException - 如果任务无法安排执行

    NullPointerException - 如果该任务为 null

submit

<T> Future<T> submit(Runnable task, T result)

    提交一个 Runnable 任务用于执行,并返回一个表示该任务的 Future。该 Future 的 get 方法在成功完成时将会返回给定的结果。

    参数:

    task - 要提交的任务

    result - 返回的结果

    返回:

        表示任务等待完成的 Future

    抛出:

    RejectedExecutionException - 如果任务无法安排执行

    NullPointerException - 如果该任务为 null

submit

Future<?> submit(Runnable task)

    提交一个 Runnable 任务用于执行,并返回一个表示该任务的 Future。该 Future 的 get 方法在 成功 完成时将会返回 null。

    参数:

    task - 要提交的任务

    返回:

        表示任务等待完成的 Future

    抛出:

    RejectedExecutionException - 如果任务无法安排执行

    NullPointerException - 如果该任务为 null

invokeAll

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

    执行给定的任务,当所有任务完成时,返回保持任务状态和结果的 Future 列表。返回列表的所有元素的 Future.isDone() 为 true。注意,可以正常地或通过抛出异常来终止 已完成 任务。如果正在进行此操作时修改了给定的 collection,则此方法的结果是不确定的。

    参数:

    tasks - 任务 collection

    返回:

        表示任务的 Future 列表,列表顺序与给定任务列表的迭代器所生成的顺序相同,每个任务都已完成。

    抛出:

    InterruptedException - 如果等待时发生中断,在这种情况下取消尚未完成的任务。

    NullPointerException - 如果任务或其任意元素为 null

    RejectedExecutionException - 如果所有任务都无法安排执行

invokeAll

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

    执行给定的任务,当所有任务完成或超时期满时(无论哪个首先发生),返回保持任务状态和结果的 Future 列表。返回列表的所有元素的 Future.isDone() 为 true。一旦返回后,即取消尚未完成的任务。注意,可以正常地或通过抛出异常来终止 已完成 任务。如果此操作正在进行时修改了给定的 collection,则此方法的结果是不确定的。

    参数:

    tasks - 任务 collection

    timeout - 最长等待时间

    unit - timeout 参数的时间单位

    返回:

    表示任务的 Future 列表,列表顺序与给定任务列表的迭代器所生成的顺序相同。如果操作未超时,则已完成所有任务。如果确实超时了,则某些任务尚未完成。

    抛出:

    InterruptedException - 如果等待时发生中断,在这种情况下取消尚未完成的任务

    NullPointerException - 如果任务或其任意元素或 unit 为 null

    RejectedExecutionException - 如果所有任务都无法安排执行

invokeAny

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

    执行给定的任务,如果某个任务已成功完成(也就是未抛出异常),则返回其结果。一旦正常或异常返回后,则取消尚未完成的任务。如果此操作正在进行时修改了给定的 collection,则此方法的结果是不确定的。

    参数:

    tasks - 任务 collection

    返回:

        某个任务返回的结果

    抛出:

    InterruptedException - 如果等待时发生中断

    NullPointerException - 如果任务或其任意元素为 null

    IllegalArgumentException - 如果任务为空

    ExecutionException - 如果没有任务成功完成

    RejectedExecutionException - 如果任务无法安排执行

invokeAny

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

    执行给定的任务,如果在给定的超时期满前某个任务已成功完成(也就是未抛出异常),则返回其结果。一旦正常或异常返回后,则取消尚未完成的任务。如果此操作正在进行时修改了给定的 collection,则此方法的结果是不确定的。

    参数:

    tasks - 任务 collection

    timeout - 最长等待时间

    unit - timeout 参数的时间单位

    返回:

        某个任务返回的结果

    抛出:

    InterruptedException - 如果等待时发生中断

    NullPointerException - 如果任务或其任意元素或 unit 为 null

    TimeoutException - 如果在所有任务成功完成之前给定的超时期满

    ExecutionException - 如果没有任务成功完成

    RejectedExecutionException - 如果任务无法安排执行

调用实例:

  • invokeAny取得第一个方法的返回值,当第一个任务结束后,会调用interrupt方法中断其它任务。
  • invokeAll等线程任务执行完毕后,取得全部任务的结果值。

invokeAll(tasks)

package com.thread;


import java.util.ArrayList;
import java.util.List;
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 InvokeAllTest implements Callable<String> {
    int a = 0;

    public InvokeAllTest(int a){
        this.a=a;
    }

    @Override
    public String call(){
        System.out.println("当前值为:" + a);
        return Integer.toString(a);
    }

    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(3);
        List<Callable<String>> list = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            list.add(new InvokeAllTest(i));
        }
        try {
            List<Future<String>> futures = executorService.invokeAll(list);
            for (Future<String> future : futures) {
                System.out.println("返回值:"+future.get());
            }
        } catch (InterruptedException e) {//invokeAll 可能抛出的异常
            e.printStackTrace();
        } catch (ExecutionException e) {//future.get() 可能抛出的异常
            e.printStackTrace();
        }
        executorService.shutdown();
    }
}

    运行结果:

当前值为:0
当前值为:2
当前值为:3
当前值为:4
当前值为:1
返回值:0
返回值:1
返回值:2
返回值:3
返回值:4

    如果在call方法中抛出异常了,只有在main方法调用了future.get(),main线程才能捕获到异常:

    1.不调用future.get():

package com.thread;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class InvokeAllTest implements Callable<String> {
    int a = 0;

    public InvokeAllTest(int a) {
        this.a = a;
    }

    @Override
    public String call(){
        System.out.println("当前值为:" + a);
        if (a == 2) {
            throw new RuntimeException();
        }

        return Integer.toString(a);
    }

    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(3);
        List<Callable<String>> list = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            list.add(new InvokeAllTest(i));
        }
        try {
            executorService.invokeAll(list);
        } catch (InterruptedException e) {//invokeAll 可能抛出的异常
            e.printStackTrace();
        }
        executorService.shutdown();
    }
}

    运行结果:

当前值为:0
当前值为:1
当前值为:3
当前值为:4
当前值为:2

    调用 future.get():

package com.thread;

import java.util.ArrayList;
import java.util.List;
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 InvokeAllTest implements Callable<String> {
    int a = 0;

    public InvokeAllTest(int a) {
        this.a = a;
    }

    @Override
    public String call(){
        System.out.println("当前值为:" + a);
        if (a == 2) {
            throw new RuntimeException();
        }

        return Integer.toString(a);
    }

    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(3);
        List<Callable<String>> list = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            list.add(new InvokeAllTest(i));
        }
        try {
            List<Future<String>> futures = executorService.invokeAll(list);
            for (Future<String> future : futures) {
                System.out.println("返回值:" + future.get());
            }
        } catch (InterruptedException e) {//invokeAll 可能抛出的异常
            e.printStackTrace();
        } catch (ExecutionException e) {//future.get() 可能抛出的异常
            e.printStackTrace();
        }
        executorService.shutdown();
    }
}

    运行结果:

当前值为:0
当前值为:2
当前值为:1
当前值为:4
当前值为:3
返回值:0
返回值:1
java.util.concurrent.ExecutionException: java.lang.RuntimeException
    at java.util.concurrent.FutureTask.report(FutureTask.java:122)
    at java.util.concurrent.FutureTask.get(FutureTask.java:192)
    at com.thread.InvokeAllTest.main(InvokeAllTest.java:37)
Caused by: java.lang.RuntimeException
    at com.thread.InvokeAllTest.call(InvokeAllTest.java:22)
    at com.thread.InvokeAllTest.call(InvokeAllTest.java:11)
    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)

 invokeAll(tasks,timeout,unit)):若在指定时间内任务没有执行完毕,则interrupt 中断线程的执行;需要注意:此时无法获取到任何异常,只有当在Future对象调用get()方法时,才会抛出 CancellationException 异常。

    将上述例子:

executorService.invokeAll(list);

    修改为:

executorService.invokeAll(list, 15, TimeUnit.SECONDS);

    若在call()中有异常抛出,只有在main方法调用了future.get(),main线程才能捕获到异常。

invokeAny(tasks)

package com.thread;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class InvokeAllTest implements Callable<String> {
    int a = 0;

    public InvokeAllTest(int a) {
        this.a = a;
    }

    @Override
    public String call() {
        System.out.println("当前值为:" + a);
        
        return Integer.toString(a);
    }

    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(3);
        List<Callable<String>> list = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            list.add(new InvokeAllTest(i));
        }
        try {
            String value = executorService.invokeAny(list);
            System.out.println("最后结果值是======:" + value);
        } catch (InterruptedException e) {//invokeAll 可能抛出的异常
            e.printStackTrace();
        } catch (ExecutionException e) {//future.get() 可能抛出的异常
            e.printStackTrace();
        }
        executorService.shutdown();
    }
}

    运行结果: 

当前值为:0
当前值为:2
当前值为:3
当前值为:1
最后结果值是======:0
当前值为:4

    invokeAny取得了某一个线程返回的值之后,但是其他线程仍将继续运行,直到运行结束。

    如果任意一个任务在call()抛出了异常,并且异常没有在call()中被显示捕获处理,那么控制台将不会打印任何异常信息。

package com.thread;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class InvokeAllTest implements Callable<String> {
    int a = 0;

    public InvokeAllTest(int a) {
        this.a = a;
    }

    @Override
    public String call() throws Exception{
        if (a>0) {
            throw new Exception("error");
        }
        System.out.println("当前值为:" + a);
        return Integer.toString(a);
    }

    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(3);
        List<Callable<String>> list = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            list.add(new InvokeAllTest(i));
        }
        try {
            String value = executorService.invokeAny(list);
            System.out.println("最后结果值是======:" + value);
        } catch (InterruptedException e) {//invokeAll 可能抛出的异常
            e.printStackTrace();
        } catch (ExecutionException e) {//future.get() 可能抛出的异常
            e.printStackTrace();
        }
        executorService.shutdown();
    }
}

    运行结果:

当前值为:0
最后结果值是======:0

    若所有的任务都发生异常,那么将返回最后一个异常并且输出异常信息,最终在ExecutionException中被捕获:

package com.thread;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class InvokeAllTest implements Callable<String> {
    int a = 0;

    public InvokeAllTest(int a) {
        this.a = a;
    }

    @Override
    public String call() throws Exception{
        if (a>-1) {
            throw new Exception("error");
        }
        System.out.println("当前值为:" + a);
        return Integer.toString(a);
    }

    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(3);
        List<Callable<String>> list = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            list.add(new InvokeAllTest(i));
        }
        try {
            String value = executorService.invokeAny(list);
            System.out.println("最后结果值是======:" + value);
        } catch (InterruptedException e) {//invokeAll 可能抛出的异常
            e.printStackTrace();
        } catch (ExecutionException e) {//future.get() 可能抛出的异常
            e.printStackTrace();
        }
        executorService.shutdown();
    }
}

    运行结果:

java.util.concurrent.ExecutionException: java.lang.Exception: error
    at java.util.concurrent.FutureTask.report(FutureTask.java:122)
    at java.util.concurrent.FutureTask.get(FutureTask.java:192)
    at java.util.concurrent.AbstractExecutorService.doInvokeAny(AbstractExecutorService.java:193)
    at java.util.concurrent.AbstractExecutorService.invokeAny(AbstractExecutorService.java:215)
    at com.thread.InvokeAllTest.main(InvokeAllTest.java:33)
Caused by: java.lang.Exception: error
    at com.thread.InvokeAllTest.call(InvokeAllTest.java:20)
    at com.thread.InvokeAllTest.call(InvokeAllTest.java:10)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    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)

 invokeAny(tasks,timeout,unit)):在指定时间内取得第一个先执行完任务的结果值,如果超时,则抛出TimeoutException,并且interrupt线程。

    将上述例子:

executorService.invokeAny(list);

    修改为:

executorService.invokeAny(list, 15, TimeUnit.SECONDS);

猜你喜欢

转载自my.oschina.net/u/3858564/blog/2960526
今日推荐