我们原来所说的继承Thread或者实现Runnable的方式都无法获得线程的执行结果,除非使用共享变量或者线程通信,我们先看一下Runnable接口的源码:
public interface Runnable{
public abstract void run(){
}
}
run()的返回值为void,在任务执行完之后没有返回
继承Thread和实现Runnable这两种方式,都无法获得线程执行的结果
Callable可以弥补这一个缺点:
public interface Callable<V>{
V call() throws Exception
}
是一个泛型接口,返回值类型为传入进来的的T类型的值
注意:Callable中方法是call而不是run
使用Callable
一般配合ExecutorService来使用:
其中声明了若干个重载的submit方法
<T> Future<T> submit(Callable<T> task);
<T> Future<T> submit(Runnable task, T result); //一般不使用
Future<?> submit(Runnable task);
Future
Future就是对于具体的Runnable或者Callable任务的执行结果进行取消、查询是否完成、获取结果。必要时可以通过get方法获取执行结果,该方法会阻塞直到任务返回结果
public interface Future<V> {
boolean cancel(boolean mayInterruptIfRunning);
boolean isCancelled();
boolean isDone();
V get() throws InterruptedException, ExecutionException;
V get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException;
}
cancel:取消任务
mayInterruptIfRunning:是否可以取消正在执行的任务
isCancelled:是否成功取消
isDone:是否已经完成
get:获取执行结果,一直等到任务执行完毕才返回,阻塞等待
get(long timeout, TimeUint unit):用来获取执行结果,指定时间内,还没有获取到结果,就返回null
也就是说Future用于异步获取执行结果或取消执行任务提供了三种功能:
1)判断任务是否完成;
2)能够中断任务;
3)能够获取任务执行结果。
因为Future只是一个接口,所以是无法直接用来创建对象使用的,因此就有了下面的FutureTask。
FutureTask是Future的唯一实现
public interface RunnableFuture<V> extends Runnbale,Future<V>
void run()
}
public class FutureTask implements RunnbaleFuture<V>{
public FutureTask(Callable<V> callable)
public FutureTask(Runnable runnable,V result)
}
可以看出RunnableFuture继承了Runnable接口和Future接口,而FutureTask实现了RunnableFuture接口。所以它既可以作为Runnable被线程执行,又可以作为Future得到Callable的返回值。
这段代码不给答案啦,动手实践感受一下
public class FutureTaskUseDemo {
public static void main(String[] agrs) throws InterruptedException, ExecutionException {
ExecutorService executor = Executors.newCachedThreadPool();
/**
* 使用FutureTask的Runnable特性
*/
Thread thread = new Thread(new FutureTask<>(new BoilWater()));
thread.start();
/**
* 使用FutureTask的Callable特性------第一种写法
*/
FutureTask futureTask = new FutureTask(new BoilWater());
executor.submit(futureTask);
out.println("做饭");
Thread.sleep(2000);
out.println("饭做好了");
while (!futureTask.isDone()) {
out.println("水还没烧开呢");
Thread.sleep(1000);
}
out.println(futureTask.get());
/**
* 使用FutureTask的Callable特性------第二种写法
*/
Future<String> submit = executor.submit(new BoilWater());
out.println("做饭");
Thread.sleep(2000);
out.println("饭做好了");
while (!submit.isDone()) {
out.println("水还没烧开呢");
Thread.sleep(1000);
}
out.println(submit.get());
/**
* 多个任务同时并行
*/
CompletionService<Integer> cs = new ExecutorCompletionService<Integer>(executor);
for (int i = 0; i < 5; i++) {
final int taskId = i;
cs.submit(() -> taskId);
}
for (int i = 0; i < 5; i++) {
try {
out.println(cs.take().get());
} catch (Exception e) {
}
}
}
}
class BoilWater implements Callable<String> {
@Override
public String call() throws Exception {
Thread.sleep(5000);
return System.currentTimeMillis() + " 水烧开了";
}
}