一、Runnable接口
它只有一个run()函数,该函数没有返回值。
@FunctionalInterface
public interface Runnable {
public abstract void run();
}
二、Callable接口
Callable与Runnable的功能大致相似,Callable中有一个call()函数,但是call()函数有返回值
@FunctionalInterface
public interface Callable<V> {
V call() throws Exception;
}
三、Future接口
Executor(线程池)就是Runnable和Callable的调度容器。
Future接口就是对具体的Runnable或者Callable任务的执行结果进行取消、查询是否完成、获取结果、设置结果等操作。
get方法会阻塞,直到任务返回结果
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;
}
四、RunnableFuture接口
是对Runnable和Future继承的一个接口,具有了他们俩的功能;
public interface RunnableFuture<V> extends Runnable, Future<V> {
void run();
}
常用实现类:FutureTask
public class FutureTask<V> implements RunnableFuture<V>
注意:FutureTask只能执行Callable类型的任务
FutureTask的构造函数会把Runnable类型转成Callable类型,所以FutureTask最终都是执行Callable类型的任务
通过RunnableAdapter适配器
由于FutureTask实现了Runnable,因此它既可以通过Thread包装来直接执行,也可以提交给ExecuteService(线程池)来执行。
并且还可以直接通过get()函数获取执行结果,该函数会阻塞,直到结果返回。
因此FutureTask既是Future、Runnable,又是Callable(包装Runnable得到的)。
FutureTask使用方法:
//线程池
ExecutorService executor = Executors.newSingleThreadExecutor();
//构造FutureTask
FutureTask<Integer> futureTask = new FutureTask<Integer>(
new Callable<Integer>() {
@Override
public Integer call() throws Exception {
Thread.sleep(1000);
return 12345;
}
});
// 提交futureTask
executor.submit(futureTask) ;
System.out.println("future result from futureTask : "+futureTask.get());
五、CompletionStage接口
CompletionStage是Java8新增接口,用于异步执行中的阶段处理。
大量使用函数式编程,需要有函数式编程的功底。
public class CompletableFuture<T> implements Future<T>, CompletionStage<T>
CompletableFuture对Future的扩展和增强。CompletableFuture实现了Future接口,并在此基础上进行了丰富的扩展,完美弥补了Future的局限性,可以轻松地组织不同任务的运行顺序、规则以及方式。
接口方法可以简单划分为三类:
1、在上一阶段执行结束之后,一阶段结果作为指定函数的参数执行函数产生新的结果,apply/combine,接口参数为Bi/Function类型
2、在上一阶段执行结束之后,一阶段结果作为指定函数的参数执行函数,accept方法,接口参数为Bi/Consumer类型
3、在上一阶段执行结束之后,不依赖一阶段执行结果,执行指定的操作,run方法,接口参数为Runnable类型
关键词:
- apply:上阶段结果作下阶段参数继续执行并返回结果
- accept:上阶段结果作下阶段参数继续执行不返回结果
- run:上阶段执行完比下阶段执行
- async:异步执行,指定或者不指定线程池
- both:前两阶段同时执行完毕执行下一阶段
- either:前两阶段任一执行完毕执行下一阶段
- combine:类似apply,但下一阶段执行的必须是BiFunction
- compose:基于上阶段的执行完状态,执行下一阶段
- complete:基于上阶段的执行完状态和结果,消费其结果
- handler:基于上阶段的执行完状态和结果,消费其正常或者异常结果
- exceptionally:消费异常结果
实现类CompletableFuture
使用方法
//线程池
ExecutorService executor = Executors.newCachedThreadPool();
//使用没有指定线程池时,CompletableFuture内部使用ForkJoinPool.commonPool()
CompletableFuture userFuture = CompletableFuture.supplyAsync(() -> {
getRemoteUserAndFill(id, userInfo);
return Boolean.TRUE;
}, executor);
CompletableFuture bonusFuture = CompletableFuture.supplyAsync(() -> {
getRemoteBonusAndFill(id, userInfo);
return Boolean.TRUE;
}, executor);
CompletableFuture growthFuture = CompletableFuture.supplyAsync(() -> {
getRemoteGrowthAndFill(id, userInfo);
return Boolean.TRUE;
}, executor);
CompletableFuture.allOf(userFuture, bonusFuture, growthFuture).join();
userFuture.get();
bonusFuture.get();
growthFuture.get();
常用于接口并行计算,优化接口。
CompletableFuture
可以指定异步处理流程:
-
thenAccept()
处理正常结果; -
exceptional()
处理异常结果; -
thenApplyAsync()
用于串行化另一个CompletableFuture
-
anyOf()
和allOf()
用于并行化多个CompletableFuture
在CompletableFuture
执行Task的时候,是需要使用线程池还是用当前的线程去执行。这个需要根据具体的情况来定。使用的时候要尽可能的小心。