Callable异步执行,应该不会陌生,那么在java中是怎么用的呢?又是如何实现的?下面我们循序渐进,慢慢分析。
先看一个例子,实现Callable接口,进行异步计算:
package com.demo;
import java.util.concurrent.*;
public class Demo {
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService executor = Executors.newCachedThreadPool();
Future<String> future = executor.submit(new Callable<String>() {
@Override
public String call() throws Exception {
System.out.println("call");
TimeUnit.SECONDS.sleep(1);
return "str";
}
});
System.out.println(future.get());
}
}
这段代码是很简单的一种方式利用Callable进行异步操作,结果自己可以执行下。
如何实现异步
在不阻塞当前线程的情况下计算,那么必然需要另外的线程去执行具体的业务逻辑,上面代码中可以看到,是把Callable放入了线程池中,等待执行,并且立刻返回futrue。可以猜想下,需要从Future中得到Callable的结果,那么Future的引用必然会被两个线程共享,一个线程执行完成后改变Future的状态位并唤醒挂起在get上的线程,到底是不是这样呢?
源码分析
首先我们从任务提交开始,在AbstractExecutorService中的源码如下:
public <T> Future<T> submit(Callable<T> task) {
if (task == null) throw new NullPointerException();
RunnableFuture<T> ftask = newTaskFor(task);
execute(ftask);
return ftask;
}
protected <T> Runn