Callable和Future

时间 2019/6/24 21:03:28 加载中...

Callable

创建线程有两个方法,一个是继承Thread类,另一个是实现Runnable接口。
但不管是哪种方法,线程都不会有返回值。

为了让线程能有返回值,于是就有了 Callable 接口。

Callabe vs Runnable

实现 Runnable 接口的类,都要实现其 run() 方法,此方法没有返回值。
实现 Callable 接口的类,都要实现其 call() 方法,且有返回值。

需要注意的是:
实现 Callable 的类并不能创建线程,要创建线程只能使用 Runnable。

实现 Callable 的类必须实现的方法:
public Object call() throws Exception;

下面是一个实现 Callable 的类,此类会返回一个随机数。

  1. import java.util.Random;
  2. import java.util.concurrent.Callable;
  3. import java.util.concurrent.FutureTask;
  4. class CallableExample implements Callable
  5. {
  6. public Object call() throws Exception
  7. {
  8. // Create random number generator
  9. Random generator = new Random();
  10. Integer randomNumber = generator.nextInt(5);
  11. // To simulate a heavy computation,
  12. // we delay the thread for some random time
  13. Thread.sleep(randomNumber * 1000);
  14. return randomNumber;
  15. }
  16. }

Future

call() 方法返回的结果肯定要放在 主线程 的一个结果对象中,这样主线程才能知道子线程返回的结果。

问题是:程序如何在过了一会后来获取到子线程的结果呢?

为个实现这个功能,Future接口就用上了。

Future就是这样的一个对象,现在不会有值,但当 call() 方法结果返回时,就会有值。
Future 就是主线程跟踪子线程进度和结果的一种途径。

我们可以了解到, Callable 和 Future 分别做了两个不同的事:

Callable 和 Runnable 类似,定义了子线程要完成的任务。
Future 是用来从子线程获取结果的。

实际上, Future 也可以和 Runnable 一起使用。

要创建一个线程, Runnable是必要的,要获取到结果,Future是必要的。
于是就有了 FutureTask类,它实现了 Runnable 和 Future 两个接口。

而 FutureTask 的构造函数中可以设定参数 Callable。这样的话 Runnable、Future、Callable 就结合起来了。

示例:

  1. import java.util.Random;
  2. import java.util.concurrent.Callable;
  3. import java.util.concurrent.ExecutionException;
  4. import java.util.concurrent.FutureTask;
  5. public class Program {
  6. public static void main(String[] args) {
  7. CallableExample callableExample = new CallableExample();
  8. FutureTask futureTask = new FutureTask(callableExample);
  9. new Thread(futureTask).start();
  10. System.out.println("main do other");
  11. try {
  12. System.out.println(futureTask.get());
  13. } catch (InterruptedException e) {
  14. e.printStackTrace();
  15. } catch (ExecutionException e) {
  16. e.printStackTrace();
  17. }
  18. System.out.println("main end");
  19. }
  20. }
  21. class CallableExample implements Callable {
  22. @Override
  23. public Object call() throws Exception {
  24. Random random = new Random();
  25. int val = random.nextInt(5);
  26. Thread.sleep(2000);
  27. return val;
  28. }
  29. }

输出结果

  1. main do other
  2. 4
  3. main end

可以看到,主线程会等待子线程执行完毕,然后才输出结果。

扫码分享
版权说明
作者:SQBER
文章来源:http://www.sqber.com/articles/callable-and-future.html
本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。