线程池将任务提交和任务执行分离,线程只是一个工作者,它可以执行有返回值的任务,也可以执行没有返回值的任务。接下将详细讨论这些线程执行的任务。
先看下执行任务基本框架:
图1 任务框架
1. Runnable
Runnable是一个没有返回值的任务,看下该接口的定义:
public interface Runnable {
//线程执行该任务时将会运行该方法
public abstract void run();
}
这个接口很简单,下面代码片断是一个简单的用法:
Thread worker = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("I'm running");
}
});
worker.start();
创建一个线程并为该线程指定一个任务,启动线程后该任务就会被执行。
2. Callable
Callable是一个有返回值的任务,看下该接口的定义:
public interface Callable<V> {
//线程执行任务时将会运行该方法
V call() throws Exception;
}
Callable的call方法可以抛出异常(包括运行时和检查异常),而Runnable的run方法不会抛出检查异常。
另外,注意到Callable是一个泛型接口,call方法的返回值是一个泛型。
3. Future
Future接口代表一个异步执行结果,它提供了检查任务是否完成的方法。在取任务执行结果时,如果任务未完成,取结果的线程会阻塞,直到任务完成并返回。
Future提供了取消任务的方法,如果执行没有返回值(例如Runnable)的任务,并且希望能够取消任务,可以定义Future
public interface Future<V> {
//尝试取消正在执行的任务,如果任务已经完成该操作就会失败。如果任务还未执行取消就会成功。
//如果任务正在执行,方法的参数就会指示线程是否需要中断,从而尝试停止任务的执行。
boolean cancel(boolean mayInterruptIfRunning);
//任务完成之前是否已经被取消
boolean isCancelled();
//任务是否已经完成
//任务正常终止、抛出异常、或者被取消,该方法都会返回true
boolean isDone();
//取任务执行的结果,如果任务未完成,取结果的线程会阻塞。
//如果任务被取消了,该方法抛出CancellationException
//如果线程被中断,抛出中断异常
V get() throws InterruptedException, ExecutionException;
//支持超时时间的get方法
//可能抛出超时异常
V get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException;
}
4. RunnableFuture
RunnableFuture继承了Runnable和Future接口。可以这样理解,RunnableFuture是一个具有异步执行结果的任务,并且可以通过Future的方法取该任务的执行结果。看下RunnableFuture接口的定义:
public interface RunnableFuture<V> extends Runnable, Future<V> {
void run();
}
5. FutureTask
FutureTask是一个可取消的异步任务,实现了RunnableFuture接口。
FutureTask所代表的任务执行有7种状态,分别由7个静态私有变量表示,我们先看下这7个状态: