1 Future接口
主要用于定义接受异步执行的结果,我们下面主要看他的实现类。参看5
public interface Future<V> {
boolean cancel(boolean mayInterruptIfRunning);
boolean isCancelled();
boolean isDone();
V get() throws InterruptedException, ExecutionException;
V get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException;
}
2 RunnableFuture接口
该接口继承了Future和Runnable。则具备两者的特性。
public interface RunnableFuture<V> extends Runnable, Future<V> {
void run();
}
3 Callable接口
某些情况下,我们需要得到异步线程执行的结果,那Runnable此时不能满足我们的需求,java为我们提供了另一个接口Callable。与Runnable不同的是,实现该接口的类只能由线程池进行调用,无法使用Thread进行调用。
public interface Callable<V> {
V call() throws Exception;
}
4 AbstractExecutorService的submit方法
线程的execute方法只能执行Runnable的子类。
为了能获取到线程的执行结果,我们需要使用到submit方法,该方法会返回一个Future对象。submit有三个重载方法。
public Future<?> submit(Runnable task) {
if (task == null) throw new NullPointerException();
RunnableFuture<Void> ftask = newTaskFor(task, null);
execute(ftask);
return ftask;
}
public <T> Future<T> submit(Runnable task, T result) {
if (task == null) throw new NullPointerException();
RunnableFuture<T> ftask = newTaskFor(task, result);
execute(ftask);
return ftask;
}
public <T> Future<T> submit(Callable<T> task) {
if (task == null) throw new NullPointerException();
RunnableFuture<T> ftask = newTaskFor(task);
execute(ftask);
return ftask;
}
三个重载方法的逻辑也都非常简单,就是创建一个RunnableFuture的对象,然后调用execute方法。了解过线程池的都知道,最终是执行的run方法,后面我们一起看一下FutureTask的run方法。
protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
return new FutureTask<T>(runnable, value);
}
protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
return new FutureTask<T>(callable);
}
5 FutureTask类
5.1 构造方法
入参为Callable对象
public FutureTask(Callable<V> callable) {
if (callable == null)
throw new NullPointerException();
this.callable = callable;
this.state = NEW; // ensure visibility of callable
}
入参为Runnable对象和返回结果
public FutureTask(Runnable runnable, V result) {
this.callable = Executors.callable(runnable, result);
this.state = NEW; // ensure visibility of callable
}
public static <T> Callable<T> callable(Runnable task, T result) {
if (task == null)
throw new NullPointerException();
return new RunnableAdapter<T>(task, result);
}
static final class RunnableAdapter<T> implements Callable<T> {
final Runnable task;
final T result;
RunnableAdapter(Runnable task, T result) {
this.task = task;
this.result = result;
}
public T call() {
task.run();
return result;
}
}
从上面可以看出,该构造方法最终也是创建了一个Callable对象,并实现call方法,在call方法中调用了业务的run方法来实现最终的业务调用,并且call方法返回传入的result。
注意区分这里的run方法和FutureTask自身的run方法
5.2 run方法
这里的run方法,是线程池最终调用的方法,这里执行了call方法,并将call方法的返回结果存到outcome这个全局变量中,通过get方法获取。也就是通过FutureTask获取任务的返回值。
public void run() {
//当前task状态不是新建,直接返回
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 {
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);
}
}
6 总结
7 实际使用
public static void main(String[] args) throws ExecutionException, InterruptedException {
//创建线程池
ThreadPoolExecutor executorService = new ThreadPoolExecutor(5, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<>());
//存储FutrueTask结果
ArrayList<Future<Integer>> taskList = new ArrayList<>();
for(int i=0;i<5;i++){
//执行任务
Future<Integer> task = executorService.submit(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
//这里可以执行具体得业务并返回
return 1;
}
});
taskList.add(task);
}
int total = 0;
//处理多线程返回得结果集,get方法回等到线程池执行完,或者抛出异常,这里不必通过shutdown来获取最终结果
for(Future<Integer> future : taskList){
Integer integer = future.get();
total+=integer;
}
System.out.println(total);
}