Callable、Future、FutureTask基本介绍
直接继承Thread或者实现Runnable接口都可以创建线程,但是这两种方法都有一个问题就是:没有返回值,也就是不能获取执行完的结果。 因此jdk1.5就提供了Callable接口来实现这一场景,而Future和FutureTask就可以和Callable接口配合起来使用。
Callable和Runnable的区别
Runnable不能返回一个返回值,不能抛出 checked Exception。 Callable的call方法可以有返回值,可以声明抛出异常。 Callable 配合的有一个 Future 类,通过 Future 可以了解任务执行情况,或者取消任务的执行,还可获取任务执行的结果,这些功能都是 Runnable 做不到的,Callable 的功能要比 Runnable 强大。
FutureTask的父类Future介绍
Future最常用的实现是:FutureTask(由于他继承的RunnableFuture实现了Runnable和Future) boolean cancel (boolean mayInterruptIfRunning) :取消任务的执行。参数指定是否立即中断任务执行,或者等等任务结束。boolean isCancelled () :任务是否已经取消,任务正常完成前将其取消,则返回 true。boolean isDone () :任务是否已经完成。需要注意的是如果任务正常终止、异常或取消,都将返回true。V get () throws InterruptedException, ExecutionException :等待任务执行结束,然后获得V类型的结果。InterruptedException 线程被中断异常, ExecutionException任务执行异常,如果任务被取消,还会抛出CancellationException。V get (long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException :同上面的get功能一样,多了设置超时时间。参数timeout指定超时时间,uint指定时间的单位,在枚举类TimeUnit中有相关的定义。如果计算超时,将抛出TimeoutException
Future的注意事项
当 for 循环批量获取 Future 的结果时容易长时间阻塞,get 方法调用时应使用 timeout 限制。 Future 的生命周期不能后退。一旦完成了任务,它就永久停在了“已完成”的状态,不能从头再来。
Future的缺陷
并发执行多任务 :Future只提供了get()方法来获取结果,并且是阻塞的。所以,除了等待你别无他法;无法对多个任务进行链式调用 :如果你希望在计算任务完成后执行特定动作,比如发邮件,但Future却没有提供这样的能力;无法组合多个任务 :如果你运行了10个任务,并期望在它们全部执行结束后执行特定动作,那么在Future中这是无能为力的;没有异常处理 :Future接口中没有关于异常处理的方法;
使用方式:把串行的任务并行化
import java. util. concurrent. Callable ;
import java. util. concurrent. ExecutionException ;
import java. util. concurrent. ExecutorService ;
import java. util. concurrent. Executors ;
import java. util. concurrent. FutureTask ;
import java. util. concurrent. TimeUnit ;
public class FutureTest {
public static void main ( String [ ] args) throws ExecutionException , InterruptedException {
FutureTask < String > ft1 = new FutureTask < > ( new T1Task ( ) ) ;
FutureTask < String > ft2 = new FutureTask < > ( new T2Task ( ) ) ;
FutureTask < String > ft3 = new FutureTask < > ( new T3Task ( ) ) ;
FutureTask < String > ft4 = new FutureTask < > ( new T4Task ( ) ) ;
FutureTask < String > ft5 = new FutureTask < > ( new T5Task ( ) ) ;
ExecutorService executorService = Executors . newFixedThreadPool ( 5 ) ;
executorService. submit ( ft1) ;
executorService. submit ( ft2) ;
executorService. submit ( ft3) ;
executorService. submit ( ft4) ;
executorService. submit ( ft5) ;
System . out. println ( ft1. get ( ) ) ;
System . out. println ( ft2. get ( ) ) ;
System . out. println ( ft3. get ( ) ) ;
System . out. println ( ft4. get ( ) ) ;
System . out. println ( ft5. get ( ) ) ;
executorService. shutdown ( ) ;
}
static class T1Task implements Callable < String > {
@Override
public String call ( ) throws Exception {
System . out. println ( "T1:任务正在执行..." ) ;
TimeUnit . MILLISECONDS. sleep ( 50 ) ;
return "T1:执行完成!" ;
}
}
static class T2Task implements Callable < String > {
@Override
public String call ( ) throws Exception {
System . out. println ( "T2:任务正在执行..." ) ;
TimeUnit . MILLISECONDS. sleep ( 50 ) ;
return "T2:执行完成!" ;
}
}
static class T3Task implements Callable < String > {
@Override
public String call ( ) throws Exception {
System . out. println ( "T3:任务正在执行..." ) ;
TimeUnit . MILLISECONDS. sleep ( 50 ) ;
return "T3:执行完成!" ;
}
}
static class T4Task implements Callable < String > {
@Override
public String call ( ) throws Exception {
System . out. println ( "T4:任务正在执行..." ) ;
TimeUnit . MILLISECONDS. sleep ( 50 ) ;
return "T4:执行完成!" ;
}
}
static class T5Task implements Callable < String > {
@Override
public String call ( ) throws Exception {
System . out. println ( "T5:任务正在执行..." ) ;
TimeUnit . MILLISECONDS. sleep ( 50 ) ;
return "T5:执行完成!" ;
}
}
}
运行结果
FutureTask的状态源码分析
private volatile int state;
private static final int NEW = 0 ;
private static final int COMPLETING = 1 ;
private static final int NORMAL = 2 ;
private static final int EXCEPTIONAL = 3 ;
private static final int CANCELLED = 4 ;
private static final int INTERRUPTING = 5 ;
private static final int INTERRUPTED = 6 ;
FutureTask的构造方法源码分析
public FutureTask ( Callable < V > callable) {
if ( callable == null )
throw new NullPointerException ( ) ;
this . callable = callable;
this . state = NEW;
}
public FutureTask ( Runnable runnable, V result) {
this . callable = Executors . callable ( runnable, result) ;
this . state = NEW;
}
public static < T > Callable < T > callable ( Runnable task, T result) {
if ( task == null )
throw new NullPointerException ( ) ;
return new RunnableAdapter < T > ( task, result) ;
}
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;
}
public T call ( ) {
task. run ( ) ;
return result;
}
}
FutureTask的run方法源码分析
public void run ( ) {
if ( state != NEW ||
! UNSAFE. compareAndSwapObject ( this , runnerOffset,
null , Thread . currentThread ( ) ) )
return ;
try {
Callable < V > c = callable;
if ( c != null && state == NEW) {
V result;
boolean ran;
try {
result = c. call ( ) ;
ran = true ;
} catch ( Throwable ex) {
result = null ;
ran = false ;
setException ( ex) ;
}
if ( ran)
set ( result) ;
}
} finally {
runner = null ;
int s = state;
if ( s >= INTERRUPTING)
handlePossibleCancellationInterrupt ( s) ;
}
}
protected void setException ( Throwable t) {
if ( UNSAFE. compareAndSwapInt ( this , stateOffset, NEW, COMPLETING) ) {
outcome = t;
UNSAFE. putOrderedInt ( this , stateOffset, EXCEPTIONAL) ;
finishCompletion ( ) ;
}
}
private void finishCompletion ( ) {
for ( WaitNode q; ( q = waiters) != null ; ) {
if ( UNSAFE. compareAndSwapObject ( this , waitersOffset, q, null ) ) {
for ( ; ; ) {
Thread t = q. thread;
if ( t != null ) {
q. thread = null ;
LockSupport . unpark ( t) ;
}
WaitNode next = q. next;
if ( next == null )
break ;
q. next = null ;
q = next;
}
break ;
}
}
done ( ) ;
callable = null ;
}
protected void set ( V v) {
if ( UNSAFE. compareAndSwapInt ( this , stateOffset, NEW, COMPLETING) ) {
outcome = v;
UNSAFE. putOrderedInt ( this , stateOffset, NORMAL) ;
finishCompletion ( ) ;
}
}
private void handlePossibleCancellationInterrupt ( int s) {
if ( s == INTERRUPTING)
while ( state == INTERRUPTING)
Thread . yield ( ) ;
}
FutureTask的get方法源码分析
public V get ( ) throws InterruptedException , ExecutionException {
int s = state;
if ( s <= COMPLETING)
s = awaitDone ( false , 0L ) ;
return report ( s) ;
}
public V get ( long timeout, TimeUnit unit)
throws InterruptedException , ExecutionException , TimeoutException {
if ( unit == null )
throw new NullPointerException ( ) ;
int s = state;
if ( s <= COMPLETING &&
( s = awaitDone ( true , unit. toNanos ( timeout) ) ) <= COMPLETING)
throw new TimeoutException ( ) ;
return report ( s) ;
}
private int awaitDone ( boolean timed, long nanos)
throws InterruptedException {
final long = timed ? System . nanoTime ( ) + nanos : 0L ;
WaitNode q = null ;
boolean queued = false ;
for ( ; ; ) {
if ( Thread . interrupted ( ) ) {
removeWaiter ( q) ;
throw new InterruptedException ( ) ;
}
int s = state;
if ( s > COMPLETING) {
if ( q != null )
q. thread = null ;
return s;
}
else if ( s == COMPLETING)
Thread . yield ( ) ;
else if ( q == null )
q = new WaitNode ( ) ;
else if ( ! queued)
queued = UNSAFE. compareAndSwapObject ( this , waitersOffset,
q. next = waiters, q) ;
else if ( timed) {
nanos = deadline - System . nanoTime ( ) ;
if ( nanos <= 0L ) {
removeWaiter ( q) ;
return state;
}
LockSupport . parkNanos ( this , nanos) ;
}
else
LockSupport . park ( this ) ;
}
}
private V report ( int s) throws ExecutionException {
Object x = outcome;
if ( s == NORMAL)
return ( V ) x;
if ( s >= CANCELLED)
throw new CancellationException ( ) ;
throw new ExecutionException ( ( Throwable ) x) ;
}
结束语
获取更多本文的前置知识文章,以及新的有价值的文章,让我们一起成为架构师! 关注公众号,可以让你对MySQL、并发编程、spring源码有深入的了解! 关注公众号,后续持续高效的学习JVM! 这个公众号,无广告!!!每日更新!!!