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(); } }