在早期的学习过程中,创建线程一般常用的就是实现Runnable接口,但这样在日渐壮大的场景中,已经不足以使用了,于是就诞生了Callable。
实现Runnable()
class MyRun implements Runnable{
@Override
public void run() {
System.out.println("come in runnable");
}
}
实现Callable()
class MyCall implements Callable<Integer> {
@Override
public Integer call() throws Exception {
System.out.println("come in callable");
return 1024;
}
}
这两者最大的区别就在于Runable没有返回值,没有抛异常,而Callable可以指定返回类型并返回值,而且有抛异常。
但是在new Thread()时,构造器只有Runnable,而没有Callable。
public Thread(Runnable target) {
init(null, target, "Thread-" + nextThreadNum(), 0);
}
如何使用Callable
就是找到一个Runable接口的实现类,并使用了Callable的类!
这个RunnableFuture就继承了Runnable()
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又实现了RunnableFuture
public class FutureTask<V> implements RunnableFuture<V>
FutureTask有个构造方法就是放了一个Callable
public FutureTask(Callable<V> callable) {
if (callable == null)
throw new NullPointerException();
this.callable = callable;
this.state = NEW; // ensure visibility of callable
}
所以我们就可以这样创建Callable的线程
class MyCall implements Callable<Integer> {
@Override
public Integer call() throws Exception {
System.out.println("come in callable");
return 1024;
}
}
public class CallAbleDemo {
public static void main(String[] args) throws ExecutionException, InterruptedException {
FutureTask<Integer> integerFutureTask = new FutureTask<>(new MyCall());
new Thread(integerFutureTask).start();
Integer integer = integerFutureTask.get();
System.out.println(integer);
}
}
而且当线程执行后,就可以通过FutureTask的get()方法,获取返回值。
public V get() throws InterruptedException, ExecutionException {
int s = state;
if (s <= COMPLETING)
s = awaitDone(false, 0L);
return report(s);
}
一般建议get放在最后,因为如果线程执行较慢时,需等待执行结束后获取值才能继续往下走,会造成阻塞,浪费时间!