[Logic of Java programming] Asynchronous task execution service Executor and ExecutorService

basic concept

The thread Thread represents the task to be performed and the mechanism of execution.
Java concurrent package provides a set of "asynchronous task execution service" mechanism, which separates "task submission" and "task execution".

The basic interface involved in the task execution service:

  • Runnable and Callable: represent asynchronous tasks to be executed
  • Executor and ExecutorService: Represents the execution service
  • Future: represents the result of an asynchronous task

Both Runnable and Callable are interfaces. Runnable does not return results, while Callable does. Runnable does not throw exceptions, while Callable does.

Executor represents the simplest execution service

public interface Executor {
    void execute(Runnable command);
}

A Runnable can be executed without returning a result. The interface does not limit how the task is executed, it may be to create a new thread, it may be to reuse a thread in the thread pool

ExecutorService extends Executor and defines more services.
Let’s first look at the submit method. Submit means submitting a task. The return value type is Future. After returning, it only means that the task has been submitted, not executed. Through Future, you can query asynchronous tasks. status, get final results, cancel tasks, etc.

public interface ExecutorService extends Executor { 
    // 对于Callable,任务最终有个返回值
    <T> Future<T> submit(Callable<T> task);
    // Runnable是没有返回值的,但可以提供一个结果,在异步任务结束时返回
    <T> Future<T> submit(Runnable task, T result);
    // 最终返回null
    Future<?> submit(Runnable task);
} 

Let's take a look at the definition of Future:

public interface Future<V> { 
    // 用于取消异步任务,如果任务已完成、或已取消、或由于某种原因不能取消,返回false,否则返回true
    // 如果任务还未开始,则不再运行。如果任务已经在运行,则不一定能取消   
    // 参数mayInterruptIfRunning表示,如果任务正在执行,是否调用interrupt方法中断线程,如果为false就不会,如果为true就会尝试中断线程,中断不一定能取消线程  
    boolean cancel(boolean mayInterruptIfRunning);   
    // 表示任务是否被取消,只要cancel方法返回了true,随后的isCancelled方法都会返回true,即使执行任务的线程还未真正结束  
    boolean isCancelled(); 
    // 表示任务是否结算,不管什么原因导致结束的
    boolean isDone(); 
    // 返回执行结果,如果任务是Runnable且没有提供结果,返回null
    // 任务被取消了,会抛出CancellationException 
    V get() throws InterruptedException, ExecutionException; 
    V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException;
}

basic use

public class Test {
    static class Task implements Callable<Integer> {
        @Override
        public Integer call() throws Exception {
            int sleepSeconds = new Random().nextInt(1000);
            Thread.sleep(sleepSeconds);
            return sleepSeconds;
        }
    }

    public static void main(String[] args) throws InterruptedException {
        // 创建一个任务执行服务
        ExecutorService executor = Executors.newSingleThreadExecutor();
        Future<Integer> future = executor.submit(new Task());
        Thread.sleep(100);
        try {
            System.out.println(future.get());
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        // 关闭任务执行服务
        executor.shutdown();
    }
}

ExecutorService also has the following methods:

public interface ExecutorService extends Executor { 
    // 不再接受新任务,但已提交的任务会继续执行,即使任务还未执行
    void shutdown();
    // 不接口新任务,且会终止已提交但未执行的任务,对于正在执行的任务,一般会调用线程的interrupt方法尝试中断
    // 返回已提交但尚未执行的任务列表  
    List<Runnable> shutdownNow();   

    // showdown和showdownNow不会阻塞,它们返回后不代表所有任务都已结束,但isShutdown会返回ture
    boolean isShutdown();

    // 除非首先调用shutdown或shutdownNow,否则isTerminated永不为true。
    // 当调用shutdown()方法后,并且所有提交的任务完成后返回为true;
    // 当调用shutdownNow()方法后,成功停止后返回为true;
    boolean isTerminated(); 

    // 等待所有任务结束,可以限定等待的时间 
    // 如果超时前所有任务都结束了,则返回true,否则返回false
    boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException;

    // 等待所有任务完成,返回Future列表 
    // 每个Future的isDone都返回true,不过isDone不代表任务执行成功了,可能是被取消了 
    <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;     
}

Implementation principle

The main implementation class of ExecutorService is ThreadPoolExecutor, which is implemented based on threads and inherits from AbstractExecutorService. AbstractExecutorService is an abstract class that implements some methods of ExecutorService.

AbstractExecutorService

AbstractExecutorService provides default implementations of submit, invokeAll, and invokeAny, and subclasses need to implement other methods.
In addition to execute, other methods are related to the life cycle management of the execution service. Submit/invokeAll/invokeAny will eventually call execute, and execute determines how to execute the task.

We can first look at the submit method

public <T> Future<T> submit(Callable<T> task) {
    if (task == null) throw new NullPointerException();
    RunnableFuture<T> ftask = newTaskFor(task);
    execute(ftask);
    return ftask;
}

Calling newTaskFor generates a RunnableFuture. RunnableFuture is an interface that extends both Runnable and Future without defining new methods. As a Runnable it represents the task to be executed and passed to execute for execution; as a Future it represents the asynchronous result of the task execution.

Let's look at newTaskFor again

protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
    return new FutureTask<T>(callable);
}

FutureTask implements the RunnableFuture interface

FutureTask

public class FutureTask<V> implements RunnableFuture<V> {
    // 表示状态  
    private volatile int state;
    // 刚开始的状态或任务在运行
    private static final int NEW          = 0;
    // 临时状态,任务即将结果,在设置结果
    private static final int COMPLETING   = 1;
    // 任务正常执行完成
    private static final int NORMAL       = 2;
    // 任务执行抛出异常结束
    private static final int EXCEPTIONAL  = 3;
    // 任务被取消
    private static final int CANCELLED    = 4;
    // 任务在被中断
    private static final int INTERRUPTING = 5;
    // 任务被中断
    private static final int INTERRUPTED  = 6;

    // 表示待执行的任务
    private Callable<V> callable;

    // 表示最终的执行结果或异常
    private Object outcome;

    // 表示运行任务的线程
    private volatile Thread runner;

    // 单向链表,表示等待任务执行结果的线程
    private volatile WaitNode waiters;

    public FutureTask(Callable<V> callable) {
        if (callable == null)
            throw new NullPointerException();
        this.callable = callable;
        // 初始化状态
        this.state = NEW;       // ensure visibility of callable
    }

    public FutureTask(Runnable runnable, V result) {
        // 如果传入的是runnable,则转换为callable
        this.callable = Executors.callable(runnable, result);
        this.state = NEW;       // ensure visibility of callable
    }
}

The task execution service will use a thread to execute the run method of FutureTask

public void run() {
    if (state!= NEW ||
        !UNSAFE.compareAndSwapObject(this, runnerOffset,
                                     null, Thread.currentThread()))
        return;
    try {
        Callable<V> c = callable;
        if (c != null && state == NEW) {
            V result;
            boolean ran;
            try {
                // 调用callable的call方法
                result = c.call();
                ran = true;
            } catch (Throwable ex) {
                // 捕捉异常,异常保存到outcome并调用finishCompletion唤醒所有等待结果的线程
                result = null;
                ran = false;
                setException(ex);
            }
            // 设置结果,保存到outcome并调用finishCompletion唤醒所有等待结果的线程
            if (ran)
                set(result);
        }
    } finally {
        // runner must be non-null until state is settled to
        // prevent concurrent calls to run()
        runner = null;
        // state must be re-read after nulling runner to prevent
        // leaked interrupts
        int s = state;
        if (s >= INTERRUPTING)
            handlePossibleCancellationInterrupt(s);
    }
}

The task submitter, gets the result through the get method,

public V get(long timeout, TimeUnit unit)
    throws InterruptedException, ExecutionException, TimeoutException {
    if (unit == null)
        throw new NullPointerException();
    int s = state;
    // 如果任务还未执行完毕就等待
    if (s <= COMPLETING &&
        (s = awaitDone(true, unit.toNanos(timeout))) <= COMPLETING)
        throw new TimeoutException();
    // 调用report报告结果,report根据状态返回结果或抛出异常
    return report(s);
}

private V report(int s) throws ExecutionException {
    Object x = outcome;
    if (s == NORMAL)
        return (V)x;
    if (s >= CANCELLED)
        throw new CancellationException();
    throw new ExecutionException((Throwable)x);
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325875078&siteId=291194637