Callable和Future


Callable
创建线程有两个方法,一个是继承Thread类,另一个是实现Runnable接口。
但不管是哪种方法,线程都不会有返回值。
为了让线程能有返回值,于是就有了 Callable 接口。
Callabe vs Runnable
实现 Runnable 接口的类,都要实现其 run() 方法,此方法没有返回值。
实现 Callable 接口的类,都要实现其 call() 方法,且有返回值。
需要注意的是:
实现 Callable 的类并不能创建线程,要创建线程只能使用 Runnable。
实现 Callable 的类必须实现的方法:public Object call() throws Exception;
下面是一个实现 Callable 的类,此类会返回一个随机数。
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
class CallableExample implements Callable
{
public Object call() throws Exception
{
// Create random number generator
Random generator = new Random();
Integer randomNumber = generator.nextInt(5);
// To simulate a heavy computation,
// we delay the thread for some random time
Thread.sleep(randomNumber * 1000);
return randomNumber;
}
}
Future
call() 方法返回的结果肯定要放在 主线程 的一个结果对象中,这样主线程才能知道子线程返回的结果。
问题是:程序如何在过了一会后来获取到子线程的结果呢?
为个实现这个功能,Future接口就用上了。
Future就是这样的一个对象,现在不会有值,但当 call() 方法结果返回时,就会有值。
Future 就是主线程跟踪子线程进度和结果的一种途径。
我们可以了解到, Callable 和 Future 分别做了两个不同的事:
Callable 和 Runnable 类似,定义了子线程要完成的任务。
Future 是用来从子线程获取结果的。
实际上, Future 也可以和 Runnable 一起使用。
要创建一个线程, Runnable是必要的,要获取到结果,Future是必要的。
于是就有了 FutureTask类,它实现了 Runnable 和 Future 两个接口。
而 FutureTask 的构造函数中可以设定参数 Callable。这样的话 Runnable、Future、Callable 就结合起来了。
示例:
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class Program {
public static void main(String[] args) {
CallableExample callableExample = new CallableExample();
FutureTask futureTask = new FutureTask(callableExample);
new Thread(futureTask).start();
System.out.println("main do other");
try {
System.out.println(futureTask.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
System.out.println("main end");
}
}
class CallableExample implements Callable {
@Override
public Object call() throws Exception {
Random random = new Random();
int val = random.nextInt(5);
Thread.sleep(2000);
return val;
}
}
输出结果
main do other
4
main end
可以看到,主线程会等待子线程执行完毕,然后才输出结果。
*昵称:
*邮箱:
个人站点:
*想说的话: