Callable、FutureTask和Future

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

}

 

猜你喜欢

转载自woodding2008.iteye.com/blog/2328741