Java java.util.concurrent.ExecutorService接口方法介绍

x33g5p2x  于2021-08-22 转载在 Java  
字(5.8k)|赞(0)|评价(0)|浏览(356)

在这篇文章中,我们将通过实例学习ExecutorService接口的重要方法。

ExecutorService接口概述

ExecutorService接口为execute补充了一个类似的、但更通用的submit方法。和execute一样,submit接受Runnable对象,但也接受Callable对象,它允许任务返回一个值。submit方法返回一个Future对象,用于检索Callable返回值,并管理Callable和Runnable任务的状态。

ExecutorService还提供了提交Callable对象的大型集合的方法。最后,ExecutorService提供了许多方法来管理执行器的关闭。为了支持立即关机,任务应该正确处理中断。

JDK库中的ExecutorService接口源代码

public interface ExecutorService extends Executor {

    void shutdown();

    List<Runnable> shutdownNow();

    boolean isShutdown();

    boolean isTerminated();

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

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

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

    Future<?> submit(Runnable task);

    <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;
    <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接口方法

  • boolean awaitTermination(long timeout, TimeUnit unit) - 阻止所有任务在关闭请求后完成执行,或超时发生,或当前线程被中断,以先发生者为准。
  • List<Future> invokeAll(Collection<? extends Callable> tasks) - 执行给定的任务,当所有任务完成后,返回一个持有其状态和结果的Futures列表。
  • List<Future> invokeAll(Collection<? extends Callable> tasks, long timeout, TimeUnit unit) - 执行给定的任务,当所有任务完成或超时结束时(以先发生者为准),返回保持其状态和结果的期货列表。
  • T invokeAny(Collection<? extends Callable> tasks) - 执行给定的任务,如果有任务成功完成(即没有抛出异常),则返回其中的结果。
  • T invokeAny(Collection<? extends Callable> tasks, long timeout, TimeUnit unit) -执行给定的任务,如果有任务在给定的超时时间内完成,则返回已经成功完成(即没有抛出异常)的结果。
  • boolean isShutdown() - 如果这个执行器已经被关闭,则返回true。
  • boolean isTerminated() -如果所有的任务在关闭后都已完成,则返回true。
  • void shutdown() - 启动有序的关闭,在此过程中,先前提交的任务被执行,但不接受新任务。
  • List shutdownNow() - 试图停止所有正在执行的任务,停止处理等待中的任务,并返回一个等待执行的任务的列表。
  • Future submit(Callable task) - 提交一个返回值的任务供执行,并返回一个代表该任务的等待结果的Future。
  • Future<?> submit(Runnable task) - 提交一个Runnable任务供执行,并返回一个代表该任务的Future。
  • Future submit(Runnable task, T result) - 提交一个可运行的任务供执行,并返回一个代表该任务的Future。

ExecutorService接口示例

让我们通过例子来演示重要的ExecutorService接口方法的用法。在这个例子中,如何创建一个执行器服务并在执行器中执行一个任务。我们使用Executors.newSingleThreadExecutor()方法来创建一个ExecutorService,使用一个工作线程来执行任务。

//*/*
/* ExecutorService interface Example
/* @author javaguides.net
/*
/*/
public class ExecutorServiceExample {
    public static void main(String[] args) {

        System.out.println("Thread main started");
  
       // Create a task
        Runnable task = () -> {
             for (int i = 0; i < 5; i++) {
                 System.out.println("[" + Thread.currentThread().getName() + "] " + "Message " + i);
             }
        };

        ExecutorService executorService = Executors.newSingleThreadExecutor();

        executorService.execute(task);

        executorService.shutdown();

        System.out.println("Thread main finished");

     }
}

输出:

Thread main started
Thread main finished
[pool-1-thread-1] Message 0
[pool-1-thread-1] Message 1
[pool-1-thread-1] Message 2
[pool-1-thread-1] Message 3
[pool-1-thread-1] Message 4

让我们了解一下execute()submit()方法之间的区别。

*execute()submit()*方法之间的区别

  1. 主要区别是*submit()*方法返回Future对象以跟踪结果,而execute()方法不返回任何东西。
  2. 1.submit()和execute()方法都是用来提交一个任务给Executor框架进行异步执行。
  3. submit()方法可以同时接受Runnable和Callable任务,但execute()方法只能接受Runnable任务。
  4. 你可以从ExecutorService接口访问submit()execute(),因为它也扩展了Executor接口,该接口声明了execute()方法。
    如果你运行上述程序,你会注意到程序从未退出,因为,执行者服务一直在监听新的任务,直到我们明确关闭它。

关闭ExecutorService

ExecutorService为关闭一个执行器提供了两种方法--shutdown()

shutdown() - 当shutdown()方法在一个执行者服务上被调用时,它停止接受新任务,等待以前提交的任务执行,然后终止执行者。
shutdownNow() - 这个方法会中断正在运行的任务,并立即关闭执行器。
我们应该在程序的末尾添加关闭代码,这样它就会优雅地退出 -

executorService.shutdown();

有多个线程和任务的ExecutorService例子

让我们使用Executors.newFixedThreadPool(int nThreads)方法创建一个线程池,重用固定数量的线程在一个共享的无界队列中运行。

在前面的例子中,我们创建了一个ExecutorService,它使用一个工人线程。但当我们创建一个线程池并在线程池中并发执行多个任务时,ExecutorService的真正威力才会显现出来。
下面的例子显示了如何创建一个使用线程池的执行器服务,并同时执行多个任务 -

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

//*/*
/* ExecutorService interface Example
/* 
/* @author javaguides.net
/*
/*/
public class ExecutorServiceExample {
    public static void main(String[] args) {

        System.out.println("Thread main started");

        // Create a task
        Runnable task1 = () -> {
            for (int i = 0; i < 5; i++) {
                System.out.println("[" + Thread.currentThread().getName() + "] " + "Message " + i);
            }
        };

       // Create a task
        Runnable task2 = () -> {
            for (int i = 0; i < 5; i++) {
                 System.out.println("[" + Thread.currentThread().getName() + "] " + "Message " + i);
            }
        };

      // Create a task
       Runnable task3 = () -> {
           for (int i = 0; i < 5; i++) {
               System.out.println("[" + Thread.currentThread().getName() + "] " + "Message " + i);
           }
       };

    // Create a task
      Runnable task4 = () -> {
          for (int i = 0; i < 5; i++) {
              System.out.println("[" + Thread.currentThread().getName() + "] " + "Message " + i);
          }
      };
      ExecutorService executorService = Executors.newFixedThreadPool(2);

      executorService.execute(task1);
      executorService.execute(task2);
      executorService.execute(task3);
      executorService.execute(task4);
 
      System.out.println("Thread main finished");

      executorService.shutdown();
   }
}

输出:

Thread main started
Thread main finished
[pool-1-thread-1] Message 0
[pool-1-thread-1] Message 1
[pool-1-thread-1] Message 2
[pool-1-thread-1] Message 3
[pool-1-thread-1] Message 4
[pool-1-thread-1] Message 0
[pool-1-thread-1] Message 1
[pool-1-thread-1] Message 2
[pool-1-thread-1] Message 3
[pool-1-thread-1] Message 4
[pool-1-thread-1] Message 0
[pool-1-thread-1] Message 1
[pool-1-thread-1] Message 2
[pool-1-thread-1] Message 3
[pool-1-thread-1] Message 4
[pool-1-thread-2] Message 0
[pool-1-thread-2] Message 1
[pool-1-thread-2] Message 2
[pool-1-thread-2] Message 3
[pool-1-thread-2] Message 4

在上面这个例子中,我们创建了2个线程并执行了4个任务。看看输出,只有2个线程pool-1-thread-1和pool-1-thread-2被重用来执行4个任务。
###参考

https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html

相关文章