Callable和FutureTask的用途
创建线程
创建线程有四种方法:
- 继承Thread类
- 实现Runnable接口
- 实现Callable接口
- 使用线程池创建线程
继承Thread类
public class Thread1 extends Thread{
private String name;
public TestThread(String name){
this.name=name;
}
@Override
public void run(){
for(int i=0;i<10;i++){
System.out.println(name);
}
}
}
实现Runnable接口
public class Thread2 implements Runnable{
private String name;
public TestThread(String name){
this.name=name;
}
@Override
public void run(){
for(int i=0;i<10;i++){
System.out.println(name);
}
}
}
既然已经有了上面两种创建线程的方式,为什么还要有剩下两种呢?
Java现在的多线程机制,核心方法run是没有返回值的;如果要保存run方法里面的计算结果,必须等待run方法计算完,无论计算过程多么耗时。
那么就会想,能不能让子线程在计算的时候,让主线程异步执行呢?
这就要引出我们的Callable和FutureTask了
Callable&FutureTask
Callable
Callable是一个接口,源码如下:
public interface Callable<V> {
/**
* Computes a result, or throws an exception if unable to do so.
*
* @return computed result
* @throws Exception if unable to compute a result
*/
V call() throws Exception;
}
call() 方法你可以将它看为run()方法,但是不同的一点是call()方法具有返回值。
如何通过Callable返回值
下面先看一个例子:
public class FutureTaskDemo {
public static void main(String[] args) throws ExecutionException, InterruptedException {
Callable<String> xianshiqi = new Callable<String>() {//购买显示器的线程
@Override
public String call() throws Exception {
System.out.println("购买显示器");
Thread.currentThread().sleep(1000);
System.out.println("显示器到货");
return "显示器购买成功";
}
};
FutureTask<String> buytask = new FutureTask<String>(xianshiqi);
new Thread(buytask).start();
Callable<String> zhuji = new Callable<String>() {
@Override
public String call() throws Exception {
System.out.println("购买主机");
Thread.currentThread().sleep(1000);
System.out.println("主机到货");
return "主机购买成功";
}
};
FutureTask<String> buytask1 = new FutureTask<String>(zhuji);
new Thread(buytask1).start();
if (!buytask.isDone()){
System.out.println("显示器未到货");
}
if (!buytask1.isDone()){
System.out.println("主机未到货");
}
System.out.println(buytask1.get()+buytask.get());
}
}
可以看出FutureTask接受了Callable对象,而Thread又接受了FutureTask对象(因为FutureTask实现了Runnable接口)
FutureTask
FutureTask实现了RunnableFuture接口:
public class FutureTask<V> implements RunnableFuture<V>
而RunnableFuture接口继承了Runnable和Future两个接口:
public interface RunnableFuture<V> extends Runnable, Future<V> {
/**
* Sets this Future to the result of its computation
* unless it has been cancelled.
*/
void run();
}
上面的例子中,主要用到了FutureTask的两个方法:一个是isDone(),一个是get()。下面就两个方法看一下Java是如何实现的。
isDone()
public boolean isDone() {
return state != NEW;
}
即该task状态不为new时返回true。
get()
public V get() throws InterruptedException, ExecutionException {
int s = state;
if (s <= COMPLETING)
s = awaitDone(false, 0L);
return report(s);
}
意思是如果状态还没有完成,则等待,直到完成后返回report(s).