Runnable和Callable

architecture-daylight-indoors-2187966.jpg

简介:

这两个接口都可以代表一个任务,可以被多线程执行。Runnable可以同时被Thread和ExecutorService执行,而Callable只可以被ExecutorService执行。Callable支持泛型。

源码分析:

@FunctionalInterface
public interface Runnable {
    /**
     * When an object implementing interface Runnable is used
     * to create a thread, starting the thread causes the object's
     * run method to be called in that separately executing
     * thread.
     * 

* The general contract of the method run is that it may * take any action whatsoever. * * @see java.lang.Thread#run() */ public abstract void run(); }

run方法没有返回值,没有抛出可检查异常。

@FunctionalInterface
public interface Callable {
    /**
     * Computes a result, or throws an exception if unable to do so.
     *
     * @return computed result
     * @throws Exception if unable to compute a result
     */
    V call() throws Exception;
}

call方法有通用返回值,并且方法签名上面抛出Exception。
Callable被ExecutorService执行的简单流程介绍:
ExecutorService方法声明:

/**
 * An {@link Executor} that provides methods to manage termination and
 * methods that can produce a {@link Future} for tracking progress of
 * one or more asynchronous tasks.
**/
 Future submit(Callable task);

AbstractExecutorService实现ExecutorService接口:

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

把Callable封装在FutureTask类里面

    protected  RunnableFuture newTaskFor(Callable callable) {
        return new FutureTask(callable);
    }
    public FutureTask(Callable callable) {
        if (callable == null)
            throw new NullPointerException();
        this.callable = callable;
        this.state = NEW;       // ensure visibility of callable
    }

FutureTask实现了RunnableFuture接口,RunnableFuture接口继承了Runnable, Future接口。类的功能如下解释:

/**
 * A cancellable asynchronous computation.  This class provides a base
 * implementation of {@link Future}, with methods to start and cancel
 * a computation, query to see if the computation is complete, and
 * retrieve the result of the computation.  The result can only be
 * retrieved when the computation has completed; the {@code get}
 * methods will block if the computation has not yet completed.  Once
 * the computation has completed, the computation cannot be restarted
 * or cancelled (unless the computation is invoked using
 * {@link #runAndReset}).
 *
 * 

A {@code FutureTask} can be used to wrap a {@link Callable} or * {@link Runnable} object. Because {@code FutureTask} implements * {@code Runnable}, a {@code FutureTask} can be submitted to an * {@link Executor} for execution. **/

封装完之后,执行execute(ftask)这个方法,具体实现在ThreadPoolExecutor里面,代码如下:

    public void execute(Runnable command) {
        if (command == null)
            throw new NullPointerException();
        int c = ctl.get();
        if (workerCountOf(c) < corePoolSize) {
            if (addWorker(command, true))
                return;
            c = ctl.get();
        }
        if (isRunning(c) && workQueue.offer(command)) {
            int recheck = ctl.get();
            if (! isRunning(recheck) && remove(command))
                reject(command);
            else if (workerCountOf(recheck) == 0)
                addWorker(null, false);
        }
        else if (!addWorker(command, false))
            reject(command);
    }

执行代码在addWorker里面,这个方法有点复杂,这次主要是为了记录Callable被执行的大致流程,所以具体每一行代码的含义留给以后再好好的分析、学习。其实,最终调用的还是FutureTask的run方法,如下图,这个run方法里面又调用了Callable的call方法。

    public void run() {
        if (state != NEW ||
            !RUNNER.compareAndSet(this, null, Thread.currentThread()))
            return;
        try {
            Callable c = callable;
            if (c != null && state == NEW) {
                V result;
                boolean ran;
                try {
                    result = c.call();
                    ran = true;
                } catch (Throwable ex) {
                    result = null;
                    ran = false;
                    setException(ex);
                }
                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);
        }
    }

场景:

1、异步执行任务。
2、跟踪异步执行任务的结果。

随便聊聊:

虽然分析的不够深入,并没有把每一行代码的含义都说清楚(这还是要花很多时间和精力一点点去啃的),但是已初步能看出来Callable接口是如何被执行的,其实还是依赖Runnable,然后在对应的run方法里面再显式调用call方法,只不过这中间经历了好多特意设计流程,这些设计流程,也体现出了,jdk源码的复杂和可值得学习的地方。

你可能感兴趣的:(Runnable和Callable)