Callable是比Runnable更好的一个抽象,它有泛型的返回值,也可以抛出异常。
/**
* A task that returns a result and may throw an exception.
* Implementors define a single method with no arguments called
* {@code call}.
*
* <p>The {@code Callable} interface is similar to {@link
* java.lang.Runnable}, in that both are designed for classes whose
* instances are potentially executed by another thread. A
* {@code Runnable}, however, does not return a result and cannot
* throw a checked exception.
*
* <p>The {@link Executors} class contains utility methods to
* convert from other common forms to {@code Callable} classes.
*
* @see Executor
* @since 1.5
* @author Doug Lea
* @param <V> the result type of method {@code call}
*/
@FunctionalInterface
public interface Callable<V> {
/**
* Computes a result, or throws an exception if unable to do so.
*
* @return computed result
* @throws Exception if unable to compute a result
*/
V call() throws Exception;
}
Feture为异步计算结果提供了以及执行状态提供了丰富的方法,使用Runnable时这部分工作需要额外处理。
public interface Future<V> {
/**
* Attempts to cancel execution of this task. This attempt will
* fail if the task has already completed, has already been cancelled,
* or could not be cancelled for some other reason. If successful,
* and this task has not started when {@code cancel} is called,
* this task should never run. If the task has already started,
* then the {@code mayInterruptIfRunning} parameter determines
* whether the thread executing this task should be interrupted in
* an attempt to stop the task.
*
* <p>After this method returns, subsequent calls to {@link #isDone} will
* always return {@code true}. Subsequent calls to {@link #isCancelled}
* will always return {@code true} if this method returned {@code true}.
*
* @param mayInterruptIfRunning {@code true} if the thread executing this
* task should be interrupted; otherwise, in-progress tasks are allowed
* to complete
* @return {@code false} if the task could not be cancelled,
* typically because it has already completed normally;
* {@code true} otherwise
*/
boolean cancel(boolean mayInterruptIfRunning);
/**
* Returns {@code true} if this task was cancelled before it completed
* normally.
*
* @return {@code true} if this task was cancelled before it completed
*/
boolean isCancelled();
/**
* Returns {@code true} if this task completed.
*
* Completion may be due to normal termination, an exception, or
* cancellation -- in all of these cases, this method will return
* {@code true}.
*
* @return {@code true} if this task completed
*/
boolean isDone();
/**
* Waits if necessary for the computation to complete, and then
* retrieves its result.
*
* @return the computed result
* @throws CancellationException if the computation was cancelled
* @throws ExecutionException if the computation threw an
* exception
* @throws InterruptedException if the current thread was interrupted
* while waiting
*/
V get() throws InterruptedException, ExecutionException;
/**
* Waits if necessary for at most the given time for the computation
* to complete, and then retrieves its result, if available.
*
* @param timeout the maximum time to wait
* @param unit the time unit of the timeout argument
* @return the computed result
* @throws CancellationException if the computation was cancelled
* @throws ExecutionException if the computation threw an
* exception
* @throws InterruptedException if the current thread was interrupted
* while waiting
* @throws TimeoutException if the wait timed out
*/
V get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException;
}
玩具代码
import java.util.concurrent.Callable;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
//在执行器中取消任务
public class CancelTask {
public static class Task implements Callable<String>{
@Override
public String call() throws Exception{
while(true){
System.out.printf("Task: Test\n");
//通过中断异常退出,不能捕获中断异常
Thread.sleep(100);
}
}
}
public static void main(String[] args) {
ThreadPoolExecutor executor = (ThreadPoolExecutor)Executors.newCachedThreadPool();
Task task = new Task();
System.out.printf("Main:Executing the Task \n");
Future<String> result = executor.submit(task);
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.printf("Main: Canceling the Task \n");
//true会立刻发送中断信号,false如果没有运行会停止,否则会执行完成
result.cancel(true);
System.out.printf("Main: Cancelled: %s \n", result.isCancelled());
System.out.printf("Main: Done: %s\n", result.isDone());
executor.shutdown();
System.out.printf("Main: The executor has finished\n");
}
}
FutureTask
RunnableFuture继承了Runnable接口和Future接口,而FutureTask实现了RunnableFuture接口。所以它既可以作为Runnable被线程执行,又可以作为Future得到Callable的返回值。
public class FutureTask<V> implements RunnableFuture<V> {
}
/**
* A {@link Future} that is {@link Runnable}. Successful execution of
* the {@code run} method causes completion of the {@code Future}
* and allows access to its results.
* @see FutureTask
* @see Executor
* @since 1.6
* @author Doug Lea
* @param <V> The result type returned by this Future's {@code get} method
*/
public interface RunnableFuture<V> extends Runnable, Future<V> {
/**
* Sets this Future to the result of its computation
* unless it has been cancelled.
*/
void run();
}
玩具代码
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 ControlTaskFinished {
public static class ExecutableTask implements Callable<String> {
private String name;
public String getName() {
return name;
}
public ExecutableTask(String name) {
this.name = name;
}
public String call() throws Exception {
try {
long duration = (long) (Math.random() * 10);
System.out.printf("%s:Waiting %d seconds for results. \n",
this.name, duration);
TimeUnit.SECONDS.sleep(duration);
} catch (InterruptedException e) {
}
return "Hello, world. I'm " + name;
}
}
public static class ResultTask extends FutureTask<String> {
private String name;
public ResultTask(Callable<String> callable) {
super(callable);
this.name = ((ExecutableTask) callable).getName();
}
// 覆盖done方法【默认为空方法】
protected void done() {
if (isCancelled()) {
System.out.printf("%s: Has been canceled\n", name);
} else {
System.out.printf("%s: Has finished\n", name);
}
}
}
public static void main(String[] args) {
ExecutorService executor = (ExecutorService) Executors
.newCachedThreadPool();
ResultTask resultTask[] = new ResultTask[5];
for (int i = 0; i < 5; i++) {
ExecutableTask executableTask = new ExecutableTask("Task " + i);
resultTask[i] = new ResultTask(executableTask);
// RunnableFuture继承了Runnable接口和Future接口,而FutureTask实现了RunnableFuture接口。
// 所以它既可以作为Runnable被线程执行,又可以作为Future得到Callable的返回值。
executor.submit(resultTask[i]);
}
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
for (int i = 0; i < resultTask.length; i++) {
try {
if (!resultTask[i].isCancelled()) {
System.out.printf("%s \n", resultTask[i].get());
}
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
executor.shutdown();
}
}