(Future和FutureTask)
Future类
FutureTask叫未来任务,可以将一个复杂的任务剔除出去交给另外一个线程来完成
Future主要方法
get()
get方法的行为取决于Callable任务的状态,只有以下5种情况:
- 任务正常完成:get方法会立刻返回结果
- 任务尚未完成:任务还没有开始或进行中,get将阻塞并直到任务完成。
- 任务执行过程中抛出Exception:get方法会抛出ExecutionException,这里抛出异常,是call()执行 时产生的那个异常
- 任务被取消:get方法会抛出CancellationException
- 任务超时:get方法有一个重写方法,是传入一个延迟时间的,如果时间到了还没有获得结果,get方法会抛出TimeoutException
get(long timeout,TimeUnit unit)
如果call()在规定时间内完成任务,那么就会正常获取到返回值,而如果在指定时间内没有计算出结果, 则会抛出TimeoutException
cancel()
- 如果这个任务还没有开始执行,任务会被正常取消,未来也不会被执行,返回true
- 如果任务已经完成或已经取消,则cancel()方法会执行失败,方法返回false
- 如果这个任务已经开始,这个取消方法将不会直接取消该任务,而是会根据参数 mayInterruptIfRunningg来做判断。如果是true,就会发出中断信号给这个任务。
isDone()
- 判断线程是否执行完,执行完并不代表执行成功。
isCancelled()
- 判断是否被取消
用线程池的submit方法返回Future对象
首先要给线程池提交任务,提交时线程池会立刻返回一个空的Future容器。当线程的任务一旦执行完, 也就是当我们可以获取结果时,线程池会把该结果填入到之前给我们的那个Future中去(而不是创建一 个新的Future),我们此时可以从该Future中获得任务执行的结果。
/**
* 案例:演示一个Future的使用方法
*/
public class Demo22Future {
public static void main(String[] args) {
ExecutorService service = Executors.newFixedThreadPool(10);
Future<Integer> future = service.submit(new CallableTask());
try {
//等待3秒后打印
System.out.println(future.get());
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
service.shutdown();
}
static class CallableTask implements Callable<Integer> {
@Override
public Integer call() throws Exception {
Thread.sleep(3000);
return new Random().nextInt();
}
}
}
用FutureTask来创建Future
用FutureTask来获取Future和任务的结果。FutureTask实现Runnable和Future接口 把Callable实例当作参数,生成FutureTask的对象,然后把这个对象当作一个Runnable对象,用线程池 去执行这个Runnable对象,最后通过FutureTask获取刚才执行的结果。
/**
* 案例:演示FutureTask的用法
*/
public class Demo23FutureTask {
public static void main(String[] args) {
Demo23FutureTask.Task task = new Demo23FutureTask.Task();
//FutureTask继承Future和Runnalbe接口
FutureTask<Integer> integerFutureTask = new FutureTask<>(task);
//new Thread(integerFutureTask).start();
ExecutorService service = Executors.newCachedThreadPool();
service.submit(integerFutureTask);
try {
System.out.println("task运行结果:"+integerFutureTask.get());
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
static class Task implements Callable<Integer> {
@Override
public Integer call() throws Exception {
System.out.println("子线程正在计算");
Thread.sleep(3000);
//模拟子线程处理业务逻辑
int sum = 0;
for (int i = 0; i < 100; i++) {
sum += i;
}
return sum;
}
}
}