Runnable
接口应该由那些打算通过某一线程执行其实例的类来实现。类必须定义一个称为 run
的无参数方法。
以上为Runnable接口的描述,明确可以看出,实现Runnable子类的实例是被线程来运行的。但是看看run方法的定义为void,因此,获取run方法中的处理结果比较麻烦,这时候jdk1.5提供了解决办法。1.5之后提供了
java.util.concurrent
包,该包下面有个callable<V>接口,该接口是泛型接口,泛型类型就是你的返回值类型,下面是接口定义。
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;
}
可以看到和Runnable最大的区别就是由返回值类型。这个接口可以说完全是和Runnable一样的,区别是一个是有返回值一个是无返回值。
下面我们来实现它。
public class MyCall implements Callable<String> {
@Override
public String call() throws Exception {
System.out.println("=========");
return "return value 123";
}
}
但是想想就算我们可以有返回值了,但是要如何获取这个返回值呢,也就是我们要在哪里 get()返回值呢?
Thread类中肯定是没有的,而且,如果我们new Thread类会发现没有构造函数参数为Callable<V>,这就比较尴尬了。
所以,如果让我们自己来做的话,那唯一的办法可能就是让某个类,实现Runable方法,然后这个实现类的run方法中调用callable,然后获取返回值。
实际上,Future就是这么做的,Future 表示异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的完成,并获取计算的结果。
Future本身是个接口,因为我们需要用到它的实现类 FutureTask<V>
public class FutureTask<V> implements RunnableFuture<V>
public interface RunnableFuture<V> extends Runnable, Future<V>
以上类继承结构可以看出,FutureTask同时继承了Runable以及Future,也就意味着,FutureTask可以被线程运行,同时也可以获取到线程运行后的计算结果。
然后看FutureTask的构造函数。
以上构造函数很明显,FutureTask既可以获取线程的计算结果也可以不需要返回结果。
到这里我想我们可以自己来编写测试代码了。
FutureTask<String> future = new FutureTask<String>(new MyCall());
Thread thread = new Thread(future);
thread.start();
System.out.println(future.get());
System.out.println(future.get());
输出:
=========
return value 123
return value 123
至于为什么只输出一遍=====,这就是我们之前说的,Future调用了Callable并且获取记录了返回值,而call方法他其实只走了一遍。
最后一图流。
参考资料
http://blog.csdn.net/ghsau/article/details/7451464