前言
Java线程池中的Future和FutureTask表示线程的返回结果处理类,本文简单分析Future和实现类的用法。
如何获取线程中的运算结果?
- 使用全局变量,将线程中的结果赋值给全局变量
- 使用concurrent包中的队列,使用生产者-消费者模式获取线程中的结果
- 使用Future或者FutureTask阻塞获取线程结果
Future
Future是获取任务结果和取消任务的顶层接口
get():获取任务执行结果,在获取结果之前,该任务阻塞,直到获取结果
get(long,TimeUnit):和get()方法相同,不过设置了超时时间,在超时时间内没有获取结果将阻塞,超过超时时间返回TimeoutException异常
cancel(boolean):尝试取消一个任务
1):如果任务没有开启,则该任务将永远不会执行
2):如果任务正在执行,则通过boolean确定执行该任务的线程是否应该在试图停止该任务时被中断。
3):如果任务已经完成。则取消。
isCancelled():如果任务在正常完成前取消该任务,该方法返回true;
isDone():如果任务正常完成,返回true
FutureTask
FutureTask:是Future的实现类,并且继承了Runable接口
public class FutureTask<V> implements RunnableFuture<V>
public interface RunnableFuture<V> extends Runnable, Future<V>
调用run()方法执行该任务
当一个Runnable或者Callable提交给FutureTask的时候。FutureTask存在以下几种状态
1)未启动。FutureTask.run()方法还没有被执行之前,FutureTask处于未启动状态。当创建一个FutureTask,且没有执行FutureTask.run()方法之前,这个FutureTask处于未启动状态。
2)已启动。FutureTask.run()方法被执行的过程中,FutureTask处于已启动状态。
3)已完成。FutureTask.run()方法执行完后正常结束,或被取消(FutureTask.cancel(…)),或执行FutureTask.run()方法时抛出异常而异常结束,FutureTask处于已完成状态。
当FutureTask处于未启动或已启动状态时,执行FutureTask.get()方法将导致调用线程阻塞;
当FutureTask处于已完成状态时,执行FutureTask.get()方法将导致调用线程立即返回结果或抛出异常。
当FutureTask处于未启动状态时,执行FutureTask.cancel()方法将导致此任务永远不会被执行;
当FutureTask处于已启动状态时,执行FutureTask.cancel(true)方法将以中断执行此任务线程的方式来试图停止任务;
当FutureTask处于已启动状态时,执行FutureTask.cancel(false)方法将不会对正在执行此任务的线程产生影响(让正在执行的任务运行完成);当FutureTask处于已完成状态时,执行FutureTask.cancel(…)方法将返回false。
Demo1
Callable提交给线程池,获取结果
public static void main(String[] args) throws ExecutionException, InterruptedException {
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(10, 100, 60,
TimeUnit.SECONDS, new LinkedBlockingDeque<Runnable>());
Future<String> res= threadPoolExecutor.submit(new Callable<String>() {
@Override
public String call() throws Exception {
String str="Future";
//睡5s
TimeUnit.SECONDS.sleep(5);
return str;
}
});
String s = res.get();
System.out.println(s);
}
结果;
Future
Demo2
单独一个Callable提交给FutureTask获取结果
public static void main(String[] args) throws ExecutionException, InterruptedException {
FutureTask<String> res= new FutureTask<String>(
new Callable<String>() {
@Override
public String call() throws Exception {
String str="Future";
TimeUnit.SECONDS.sleep(5);
return str;
}
}
);
res.run();
String str=res.get();
System.out.println(str);
}
结果:
Future