Future和Callable
除了线程池可以治理线程外,Future和Callable也可以治理线程。
Runnable缺陷
Runnable的run无返回值
不能抛出Checked Exception
我们通过下面实例去演示。

我们思考下为什么没有返回值呢?一般调用Runnable的类为Thread,Thread是JDK提供,我们无法做处理。
Callable接口提供了返回值。
Callable接口
Callable接口是可以有返回值和异常的,如下源码所示:

Feature类
Future可搭配Callable来使用。Feature是一个存储器
Future与Callable关系
我们可以通过Future的get方法来获取Callable接口执行的返回值;
我们可以通过Feature的isDone方法来判断Callable是否已经执行结束了,也可以取消这个任务。
call未执行完之前,用Feature的get时会阻塞,直到有返回结果
Future主要方法
主要方法如下:
1.get 任务执行完成了,则直接返回;任务未完成,get方法会进行阻塞直到任务完成;任务执行过程中抛出了异常时,get方法也会抛出异常,get只抛出ExecutionException;
任务取消时,get抛出CancellationException异常;任务超时时,抛出TimeoutException
2.get(long timeout,TimeUnit unit) 有超时的获取,参照上方法
3.cancel 取消任务执行;取消策略需要关注
4.isDone 判断线程是否执行完毕,执行完毕不代表成功执行。
5.isCancelled 是否取消

Future基本用法实例
我们给线程池提供一个任务,获取对应Future,见如下代码所示:
package com.yang.callable;
import java.util.Random;
import java.util.concurrent.*;
public class OneFutureDemo {
public static void main(String[] args) {
ExecutorService executorService= Executors.newFixedThreadPool(10);
Future<Integer> future = executorService.submit(new CallableTask<Integer>());
try {
System.out.println(future.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
executorService.shutdown();
}
static class CallableTask<I extends Number> implements Callable<Integer>{
@Override
public Integer call() throws Exception {
Thread.sleep(1000);
return new Random().nextInt();
}
}
}
运行结果如下所示:

FutureLamda实例
我们使用Lamda来实现,请看下代码:
package com.yang.callable;
import java.util.Random;
import java.util.concurrent.*;
public class FutureLamdaDemo {
public static void main(String[] args) {
ExecutorService executorService= Executors.newFixedThreadPool(10);
Callable<Integer> callable=()->{
Thread.sleep(3000);
return new Random().nextInt();
};
Future<Integer> future = executorService.submit(callable);
try {
System.out.println(future.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
executorService.shutdown();
}
}
Future批量接收实例代码
Future批量接收Callable,实例代码如下所示:
package com.yang.callable;
import java.util.ArrayList;
import java.util.Random;
import java.util.concurrent.*;
public class MultiFutureDemo {
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(2);
ArrayList<Future<Integer>> futureArrayList = new ArrayList<Future<Integer>>();
for (int i = 0; i < 10; i++) {
futureArrayList.add(executorService.submit(new CallableTask()));
}
for (int i = 0; i < 10; i++) {
try {
Integer integer = futureArrayList.get(i).get();
System.out.println(integer);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
static class CallableTask implements Callable<Integer>{
@Override
public Integer call() throws Exception {
Thread.sleep(3000);
return new Random().nextInt();
}
}
}
运行结果如下所示:

Future在执行过程中抛出了异常实例
本实例演示get方法抛出了异常,实例代码如下所示:
package com.yang.callable;
import java.util.concurrent.*;
public class GetExecption {
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(2);
Future<Integer> future=executorService.submit(new CallableTask());
try{
future.get();
}catch (IllegalArgumentException e){
System.out.println("线程内部抛出异常");
}catch (ExecutionException e){
System.out.println("执行过程中抛出异常");
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println("中断异常");
}
}
static class CallableTask implements Callable<Integer>{
@Override
public Integer call() throws Exception {
throw new IllegalArgumentException("不合法的参数异常");
}
}
}
执行结果如下:

Future的isDone实例
isDone演示如下所示:
package com.yang.callable;
import java.util.concurrent.*;
public class GetExecption {
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(2);
Future<Integer> future=executorService.submit(new CallableTask());
try{
future.get();
}catch (IllegalArgumentException e){
System.out.println("线程内部抛出异常");
}catch (ExecutionException e){
System.out.println("执行过程中抛出异常");
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println("中断异常");
}
System.out.println(future.isDone());
}
static class CallableTask implements Callable<Integer>{
@Override
public Integer call() throws Exception {
throw new IllegalArgumentException("不合法的参数异常");
}
}
}
运行结果

Future获取任务超时实例
本实例演示get的超时方法,当超时后,我们取消这个任务。我们同事演示下cancel方法传入true或者false
package com.yang.callable;
import java.util.Calendar;
import java.util.concurrent.*;
/**
* 本实例演示Future超时
*/
public class TimeoutFutureDemo {
private static String defaultAdStr = "我是默认的";
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(2);
Future<String> future = executorService.submit(new FutureTask());
try {
String s = future.get(2000, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
System.out.println("中断了");
} catch (ExecutionException e) {
System.out.println("执行异常");
} catch (TimeoutException e) {
System.out.println("超时了");
//控制是否要中断,true:允许中断
boolean cancelStatus = future.cancel(true);
System.out.println(cancelStatus);
}
}
static class FutureTask implements Callable<String> {
@Override
public String call() throws Exception {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
System.out.println("中断了,返回默认的");
return defaultAdStr;
}
return "外部获取的消息";
}
}
}
运行结果如下所示:

Cancel方法的总结
1.cancel方法支持传入true和false
2.当传入true时,需要考虑当前线程是否支持中断,中断后的业务逻辑是否正确
3.任务都已经开始,我们是否需要其执行完毕,需要则用false

浙公网安备 33010602011771号