- JDK1.8 Callable、Future和FutureTas
- Java - Callable、Future、FutureTas
- java并发 —— Runnable、Callable、Futu
- Java线程-Callable、Future、FutureTas
- java 并发callable/Future/FutureTas
- java多线程Callable,Future,FutureTas
- JUC 假设现在有10个任务,要求同时处理,并且必须所有任务全部
- 多线程 -- Future & Callable
- Java并发之Executor + Callable + Fut
- java线程:Future和Callable
线程回顾
回顾一下线程创建的两种方式:
第一、继承Thread类,重写run方法。
第二、实现Runnable接口,实现run方法。
这二者的区别就是类只能单继承,接口可以多重继承,也可以多重实现。
Callable接口
这两种方式功能上没有任何差异,且都存在一些缺陷:
第一、线程执行后,无法返回执行结果。
第二、异常抛不出来,只能线程内处理。
针对这两个问题,jdk1.5后,Doug Lea在java.util.concurrent包提出了Callable接口和Future接口解决了这些问题。Callable接口代表接收返回结果的任务,Future接口代表对具体任务结果的查询,如Callable、Runnable任务是否完成、取消、以及获取结果。
下面对比Runnable、Callable接口,显而易见,Callable接口接收泛型作为返回数据类型,方法体抛出异常。
public interface Runnable {
public abstract void run();
}
public interface Callable<V> {
V call() throws Exception;
}
Future接口
Future接口表示获取异步任务的返回结果。提供了基本方法来判断异步任务是否完成。返回结果仅在任务完成后获取的到,如果任务未完成,获取结果方法则阻塞知道任务完成为止。当然,也可以取消任务执行。当一个任务执行完成,则无法被取消。
public interface Future<V> {
/**
* 取消执行中的任务,任务执行完成,则取消失败,返回false。
* 如果任务没有调用start方法,执行cancel方法,则任务永远不会被执行。
*
* cancel方法被调用,isDone方法中会返回true,isCanceled也会返回true。
* 参数mayInterruptIfRunning 为true表示线程执行中应该被中断,否则,执行中线程将继续直到完成
*/
boolean cancel(boolean mayInterruptIfRunning);
boolean isCancelled();
/**
* 线程完成则返回true。若线程被停止、抛出异常或者取消,也会返回true。
*/
boolean isDone();
/**
* 等待任务执行完成才会返回执行结果
*/
V get() throws InterruptedException, ExecutionException;
/**
* 指定等待超时时间
*/
V get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException;
}
FutureTask
Future是接口,无法直接创建类,因此有了FutureTask类。uml类图如下:
futuretask.jpg
FutureTask同时实现了Future和Runnable接口,有两个构造方法:
第一、传入Callable<V>,很明显Callable的泛型就是任务的返回结果类型。
第二、传入Runnable和V,Runnable接口是void类型,第二参数泛型V表示任务执行结果数据类型。
public FutureTask(Callable<V> callable) {
if (callable == null)
throw new NullPointerException();
this.callable = callable;
this.state = NEW;
}
public FutureTask(Runnable runnable, V result) {
//此处实际上也是构造了一个Callable对象,看下面源码
this.callable = Executors.callable(runnable, result);
this.state = NEW;
}
// 构建实现Callable类
public static <T> Callable<T> callable(Runnable task, T result) {
if (task == null)
throw new NullPointerException();
return new RunnableAdapter<T>(task, result);
}
//该类实现Callable接口,构建方法传入Runnable、T
static final class RunnableAdapter<T> implements Callable<T> {
final Runnable task;
final T result;
RunnableAdapter(Runnable task, T result) {
this.task = task;
this.result = result;
}
// 改方法调用Runnable的run方法,并不是作为异步任务交给OS调用,仅在当前线程执行一遍run方法,然后同步返回result的结果。
public T call() {
task.run();
return result;
}
}
注意上述两个构造方法异同,第一种,call方法直接返回计算结果,这个没有一点问题;但是第二种,传入Runnable接口和返回值T,这个T是预设的返回值,什么意思呢,就是说构造方法传入什么值,它就返回什么值,可能与任务执行结果有出入,这点值得注意。












网友评论