Future模式
核心思想是异步调用,在java中内置了对Future模式的实现,主要就是Future接口、Callable接口和FutureTask类的使用
FutureTask 常用API
- boolean cancel(boolean mayInterruptIfRunning)
取消异步任务,如果异步任务还没开始,则被取消并不再开始。如果任务在运算中,参数为true则会执行异步线程的interrupt()方法。成功取消则返回true。
- boolean isDone()
异步任务还在运算返回false,否则无论任务正常结束、中途取消或发生异常都返回true
- boolean isCancelled()
判断异步任务是否在完成前被取消,判断状态>=CANCELLED
- V get() throws InterruptedException, ExecutionException
如果异步任务被取消,会抛出CancellationException异常
- V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException
设置最长阻塞时间,时间到了还get不到,抛出TimeoutException异常
Future模式一般有两种使用方式
- 使用线程池
public class FutureDemo implements Callable<String> {
@Override
public String call() throws Exception {
Thread.sleep(2000);//代替耗时的异步程序
return "result";
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
ThreadPoolExecutor pool = new ThreadPoolExecutor(
5,
5,
0,
TimeUnit.SECONDS,
new ArrayBlockingQueue<Runnable>(100),
new CustomizableThreadFactory("factoryName"),
new ThreadPoolExecutor.DiscardPolicy()
);
Future<String> future = pool.submit(new FutureDemo());
//TODO 耗时的业务
future.get();//如果异步调用执行完了则返回,否则会阻塞
}
- 直接启动一个线程执行异步操作
public class FutureDemo implements Callable<String> {
@Override
public String call() throws Exception {
Thread.sleep(2000);代替耗时的异步程序
return "result";
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
FutureTask<String> futureTask = new FutureTask<>(new FutureDemo());
new Thread(futureTask).start();
//直接调用FutureTask的run()方法不会开启新线程
//达不到异步的效果,和直接调用new Thread(futureTask).run()一样
//futureTask.run();
//TODO 耗时的业务
futureTask.get();
}
}
Tips
线程池:Future<?> submit(Runnable task)方法返回的Futuer对象,可以使用isDone()、cancel()、isCancelled(),但是调用get()方法时,当任务结束后只会返回null
用完一个线程池的时候,调用shutdown(),该池将不会接收新的任务,现存任务都结束后,池中的线程死亡。调用shutdownNow(),该池取消所有尚未开始的任务并中断正在运行的线程