天天看点

Callable、Future 和 FutureTask【享学堂】

Runnable 是一个接口,在它里面只声明了一个 run()方法,由于 run()方法返回值为 void

类型,所以在执行完任务之后无法返回任何结果。

Callable 位于 java.util.concurrent 包下,它也是一个接口,在它里面也只声明了一个方法,只不过这个方法叫做

call(),这是一个泛型接口,call()函数返回的类型就是传递进来的 V 类型。

Future 就是对于具体的 Runnable 或者 Callable 任务的执行结果进行取消、查询是否完成、获取结果。必要时可以通过

get 方法获取执行结果,该方法会阻塞直到任务返回结果。

因为 Future 只是一个接口,所以是无法直接用来创建对象使用的,因此就有了下面的 FutureTask。
Callable、Future 和 FutureTask【享学堂】
FutureTask 类实现了 RunnableFuture 接口,RunnableFuture 继承了 Runnable接口和 Future 接口,而 FutureTask 实现了 RunnableFuture 接口。所以它既可以作为 Runnable 被线程执行,又可以作为 Future 得到 Callable 的返回值。
Callable、Future 和 FutureTask【享学堂】

因此我们通过一个线程运行 Callable,但是 Thread 不支持构造方法中传递Callable 的实例,所以我们需要通过 FutureTask 把一个 Callable 包装成 Runnable,然后再通过这个 FutureTask 拿到 Callable 运行后的返回值。

创建一个 FutureTask 的实例,有两种方法

Callable、Future 和 FutureTask【享学堂】
public class CallableTest {

	public static class UserCallable implements Callable<Integer>{

		private int sum = 0;
		@Override
		public Integer call() throws Exception {
			int[] arr = IntStream.rangeClosed(1, 100).toArray();
			for (int i : arr) {
				sum += i;
			}
			return sum;
		}
	}
	//求1-100的和
	public static void main(String[] args) throws InterruptedException, ExecutionException {
		UserCallable userCallable = new UserCallable();
		FutureTask<Integer> futureTask = new FutureTask<>(userCallable);
		new Thread(futureTask).start();
		Integer sum = futureTask.get();
		System.out.println("sum = " + sum);
	}
}
           

继续阅读