多线程 Executor ExecutorService Executors Runnable Future

1. Executor

public interface Executor

执行提交的 Runnable 任务的对象。 该接口提供了一种将任务提交与每个任务将如何运行的机制分离的方法,包括线程使用、调度等细节。通常使用执行器而不是显式创建线程。 例如,不是为一组任务中的每一个调用 new Thread(new(RunnableTask())).start(),您可以使用:

1
2
3
4
Executor executor = anExecutor;
executor.execute(new RunnableTask1());
executor.execute(new RunnableTask2());
...

但是,Executor 接口并不严格要求执行是异步的。 在最简单的情况下,执行者可以在调用者的线程中立即运行提交的任务:

1
2
3
4
5
class DirectExecutor implements Executor {
public void execute(Runnable r) {
r.run();    
}  
}

更典型的是,任务在调用者线程以外的某个线程中执行。 下面的执行器为每个任务生成一个新线程。

1
2
3
4
5
6
7
class ThreadPerTaskExecutor implements Executor 
{    
public void execute(Runnable r)
{      
new Thread(r).start();    
}  
}

许多 Executor 实现对任务的调度方式和时间施加了某种限制。 下面的执行器将任务提交序列化到第二个执行器,说明了复合执行器。

此包中提供的 Executor 实现实现了 ExecutorService,这是一个更广泛的接口。 ThreadPoolExecutor 类提供了一个可扩展的线程池实现。 Executors 类为这些 Executors 提供了方便的工厂方法。 内存一致性影响:在将 Runnable 对象提交给 Executor 之前线程中的操作发生在其执行开始之前,可能是在另一个线程中。

2. ExecutorService

public interface ExecutorService extends Executor

一个 Executor,它提供管理终止的方法和可以生成用于跟踪一个或多个异步任务进度的 Future 的方法。 可以关闭 ExecutorService,这将导致它拒绝新任务。 提供了两种不同的方法来关闭 ExecutorService。 shutdown 方法将允许先前提交的任务在终止之前执行,而 shutdownNow 方法阻止等待任务启动并尝试停止当前正在执行的任务。 终止后,执行者没有正在执行的任务,没有等待执行的任务,也没有新的任务可以提交。 应关闭未使用的 ExecutorService 以允许回收其资源。 提交方法通过创建并返回可用于取消执行和/或等待完成的 Future 来扩展基本方法 Executor.execute(Runnable)。 方法 invokeAny 和 invokeAll 执行最常用的批量执行形式,执行一组任务,然后等待至少一个或所有任务完成。 (类 ExecutorCompletionService 可用于编写这些方法的自定义变体。) Executors 类为该包中提供的执行程序服务提供工厂方法。

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

提交一个有返回值的任务以供执行,并返回一个代表任务待处理结果的 Future。 Future 的 get 方法将在成功完成后返回任务结果。 如果您想立即阻止等待任务,您可以使用 result = exec.submit(aCallable).get(); 形式的结构; 注意:Executors 类包含一组方法,可以将一些其他常见的类闭包对象(例如,java.security.PrivilegedAction)转换为 Callable 形式,以便可以提交它们。 参数: 任务——要提交的任务 退货: 代表任务未决完成的 Future

1
2
3
// Blocks until all tasks have completed execution after a shutdown request, or the timeout occurs, or the current thread is interrupted, whichever happens first.
boolean awaitTermination(long timeout, TimeUnit unit)
throws InterruptedException;
1
2
3
// Submits a value-returning task for execution and returns a Future representing the pending results of the task. The Future's get method will return the task's result upon successful completion.
If you would like to immediately block waiting for a task, you can use constructions of the form result = exec.submit(aCallable).get();
<T> Future<T> submit(Callable<T> task);
1
2
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
  throws InterruptedException;

3. Executors

此包中定义的 Executor、ExecutorService、ScheduledExecutorService、ThreadFactory 和 Callable 类的工厂和实用方法。 该类支持以下几种方法:

使用常用配置设置创建和返回 ExecutorService 的方法。

使用常用配置设置创建和返回 ScheduledExecutorService 的方法。

创建并返回“包装的”ExecutorService 的方法,通过使特定于实现的方法不可访问来禁用重新配置。

创建并返回将新创建的线程设置为已知状态的 ThreadFactory 的方法。

从其他类似闭包的形式创建和返回 Callable 的方法,因此它们可以用于需要 Callable 的执行方法中。

public class Executors

1
2
3
4
5
public static ExecutorService newFixedThreadPool(int nThreads) {
       return new ThreadPoolExecutor(nThreads, nThreads,
                                     0L, TimeUnit.MILLISECONDS,
                                     new LinkedBlockingQueue<Runnable>());
  }

4. Runnable

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public interface Runnable {
  /**
    * When an object implementing interface <code>Runnable</code> is used
    * to create a thread, starting the thread causes the object's
    * <code>run</code> method to be called in that separately executing
    * thread.
    * <p>
    * The general contract of the method <code>run</code> is that it may
    * take any action whatsoever.
    *
    * @see     java.lang.Thread#run()
    */
  public abstract void run();
}

Runnable 接口应该由其实例旨在由线程执行的任何类实现。 该类必须定义一个名为 run 的无参数方法。 此接口旨在为希望在活动时执行代码的对象提供通用协议。 例如,Runnable 是由类 Thread 实现的。 处于活动状态仅意味着线程已启动且尚未停止。 此外,Runnable 提供了一种方法,可以使类在不子类化 Thread 的情况下处于活动状态。 通过实例化 Thread 实例并将自身作为目标传入,实现 Runnable 的类可以在不继承 Thread 的情况下运行。 在大多数情况下,如果您只打算覆盖 run() 方法而不打算覆盖其他 Thread 方法,则应使用 Runnable 接口。 这很重要,因为除非程序员打算修改或增强类的基本行为,否则不应将类子类化。

5. Future

Future 表示异步计算的结果。 提供了检查计算是否完成、等待其完成以及检索计算结果的方法。 结果只能在计算完成时使用 get 方法检索,必要时会阻塞直到准备就绪。 取消是通过 cancel 方法执行的。 提供了其他方法来确定任务是正常完成还是被取消。 一旦计算完成,就不能取消计算。 如果您想为了可取消性而使用 Future 但不提供可用的结果,您可以声明 Future<?> 形式的类型并返回 null 作为基础任务的结果。

FutureTask 类是实现 Runnable 的 Future 的实现,因此可以由 Executor 执行。 例如,上面带有 submit 的构造可以替换为:

public interface Future<V>

Type parameters: – The result type returned by this Future’s get method

boolean cancel(boolean mayInterruptIfRunning);

尝试取消执行此任务。 如果任务已经完成、已被取消或由于其他原因无法取消,则此尝试将失败。 如果成功,并且在调用 cancel 时此任务尚未启动,则此任务永远不会运行。 如果任务已经启动,则 mayInterruptIfRunning 参数确定是否应中断执行此任务的线程以尝试停止任务。 此方法返回后,后续对 isDone 的调用将始终返回 true。 如果此方法返回 true,则对 isCancelled 的后续调用将始终返回 true。 参数: mayInterruptIfRunning——如果执行此任务的线程应该被中断,则为真; 否则,允许完成正在进行的任务 退货: false 如果无法取消任务,通常是因为它已经正常完成; 否则为真