Callable,Future 和Runnable的使用

Future

类概述:
{@code Future} represents the result of an asynchronous computation. Methods are provided to check if the computation is complete, to wait for its completion, and to retrieve the result of the computation.
The result can only be retrieved using method {@code get} when the computation has completed, blocking if necessary until it is ready. Cancellation is performed by the {@code cancel} method.
Additional methods are provided to determine if the task completed normally or was cancelled. Once a computation has completed, the computation cannot be cancelled.
If you would like to use a {@code Future} for the sake of cancellability but not provide a usable result, you can declare types of the form {@code Future} and return {@code null} as a result of the underlying task.
Sample Usage (Note that the following classes are all made-up.注意一下的类是被组装的)
大概意思就是:
Future是一个接口,代表了一个异步计算的结果。接口中的方法用来检查计算是否完成、等待完成和得到计算的结果。
当计算完成后,只能通过get()方法得到结果,get方法会阻塞直到结果准备好了。如果想取消,那么调用cancel()方法。
其他方法用于确定任务是正常完成还是取消了。一旦计算完成了,那么这个计算就不能被取消。

{@code
interface ArchiveSearcher { String search(String target); }
class App {
ExecutorService executor = …
ArchiveSearcher searcher = …
void showSearch(final String target)
throws InterruptedException {
Future future
= executor.submit(new Callable() {
public String call() {
return searcher.search(target);
}});
displayOtherThings(); // do other things while searching
try {
displayText(future.get()); // use future
} catch (ExecutionException ex) { cleanup(); return; }
}
}};

The {@link FutureTask} class is an implementation of {@code Future} that implements {@code Runnable}, and so may be executed by an {@code Executor}. For example, the above construction with {@code submit} could be replaced by:
{@code
FutureTask future =
new FutureTask(new Callable() {
public String call() {
return searcher.search(target);
}});
executor.execute(future);}
Memory consistency effects(内存一致性): Actions taken by the asynchronous computation happen-before actions following the corresponding {@code Future.get()} in another thread. @see FutureTask @see Executor @since 1.5 @author Doug Lea @param The result type returned by this Future’s {@code get} method /

Callable,Runnable

Callable和Runnbale一样代表着任务,区别在于Callable有返回值并且可以抛出异常。其使用如下:

import java.util.concurrent.*;

public class CallableDemo {

    static class SumTask implements Callable<Long> {

        public Long call() throws Exception {

            long sum = 0;
            for (int i = 0; i < 9000; i++) {
                sum += i;
            }

            return sum;
        }
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("Start:" + System.nanoTime());
        FutureTask futureTask = new FutureTask(new SumTask());
        Executor executor=Executors.newSingleThreadExecutor();
        executor.execute(futureTask);
        System.out.println(futureTask.get());
        System.out.println("End:" + System.nanoTime());
    }

}

FutureTask类

类简述:
除了作为独立类之外,此类还提供了{@code protected}功能,这在创建自定义任务类时可能很有用。 @since 1.5 @author Doug Lea @param这个FutureTask的{@code get}方法返回的结果类型//修订说明:
这与此类依赖于AbstractQueuedSynchronizer的先前版本不同,主要是为了避免让用户惊讶地保留中断状态取消比赛。当前设计中的同步控制依赖于通过CAS更新的“状态”字段以跟踪完成,
以及用于保存等待线程的简单Treiber堆栈。样式说明:像往常一样,我们绕过了使用AtomicXFieldUpdaters的开销,而是直接使用Unsafe内在函数。
//这个任务的运行状态,最初是NEW。运行状态仅在方法set,setException和cancel中转​​换为终端状态。在完成期间,状态可以采用COMPLETING的瞬态值(当设置结果时)或INTERRUPTING(仅在中断转轮以满足取消(true)时)。
从这些中间状态到最终状态的转换使用更便宜的有序/惰性写入,因为值是唯一的并且不能进一步修改。可能的状态转换
FutureTask类实现了RunnableFuture接口,而RunnnableFuture接口继承了Runnable和Future接口,所以说FutureTask是一个提供异步计算的结果的任务。

FutureTask可以用来包装Callable或者Runnbale对象。因为FutureTask实现了Runnable接口,所以FutureTask也可以被提交给Executor(如上面例子那样)。
Callable,Future 和Runnable的使用_第1张图片
从继承中可以清楚的看到,FutureTask是Runnable和Future的综合。
到这里我们应该有些头绪了,关键点应该在FutureTask对象上,线程池不过是提供一个线程运行FutureTask中的run方法罢了。
从上面的分析,FutureTask被生产者和消费者共享,生产者运行run方法计算结果,消费者通过get方法获取结果,那么必然就需要通知,如何通知呢,肯定是状态位变化,并唤醒线程。

FutureTask状态

    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;

## 构造方法 ##
    public FutureTask(Callable callable) {
        if (callable == null)
            throw new NullPointerException();
        this.callable = callable;
        this.state = NEW;       // ensure visibility of callable
    }
    public FutureTask(Runnable runnable, V result) {
        this.callable = Executors.callable(runnable, result);
        this.state = NEW;       // ensure visibility of callable
    }


再来看第二种构造方法用到的适配器模式:

Executors代码

public static Callable callable(Runnable task, T result) {
if (task == null)
throw new NullPointerException();
return new RunnableAdapter(task, result);
}

RunnableAdapter源码

/**
 * A callable that runs given task and returns given result
 */
static final class RunnableAdapter implements Callable {
    final Runnable task;
    final T result;
    RunnableAdapter(Runnable task, T result) {
        this.task = task;
        this.result = result;
    }
    public T call() {
        task.run();
        return result;
    }
}

“`
关于Callabe异步原理解析,请参考https://blog.csdn.net/u012664375/article/details/66967687

你可能感兴趣的:(多线程)