Callable接口、Future接口、FutureTask类
以下内容转自:http://blog.csdn.net/ghsau/article/details/7451464 ;http://www.cnblogs.com/whgw/archive/2011/09/28/2194760.html
Callable接口
Callable接口类似于Runnable,但是Runnable不会返回结果,并且无法抛出返回结果的异常,而Callable功能更强大一些,被线程执行后,可以返回值,则个返回值可以被Future拿到,Future可以拿到异步执行任务的返回值。
Callable的接口定义如下;
public interface Callable<V> {
V call() throws Exception;
}
Callablle接口和Runnable接口的区别:
- Callable定义的方法是call,而Runnable定义的方法是run。
- Callable的call方法可以有返回值,而Runnable的run方法不能有返回值;
- Callable的call方法可以抛出异常,而Runnable的run方法不能抛出异常。
Future接口---------public interface Future<V>
V是词Future的get方法所返回的结果类型,Future标识异步计算的结果,它提供了检查计算是否完成的方法,以等待计算的完成,并获取计算的结果。计算完成后只能使用Get方法来获取结果。如果有必要,计算完成前可以阻塞此方法,取消则由cancle方法来执行。
如果为了可取消性而使用Future但又不提供可用的结果,则可以声明Future<?>形式类型、并返回null作为底层任务的结果。
功能:
1. boolean cancle(boolean mayInterruptIfRunning)---------试图取消对此任务的执行;一旦计算完成就不能再取消计算。参数为 true 表示立即中断任务的执行,参数为 false 表示允许正在运行的任务运行完成。
2. V get()------------如有必要,等待计算完成,然后获取其结果
3.V get(long timeout, TimeUnit unit)-----------如有必要,最多等待为使计算完成所给定的时间之后,获取其结果。
4.boolean isCancelled()----------如果在任务正常完成前将其取消,则返回true。
5.isDone()-----------如果任务已完成,则返回true。
package Test; import java.util.concurrent.*; interface ArchiveSearcher { String search(String target); } class App { ExecutorService executor = Executors.newSingleThreadExecutor(); ArchiveSearcher searcher = new ArchiveSearcher() { @Override public String search(String target) { return "zhaodaole"; } }; void showSearch(final String target) throws InterruptedException { Future<String> future = executor.submit(new Callable<String>() { public String call() { return searcher.search(target); }}); try { SystedisplayText(future.get()); } catch (ExecutionException ex) { return; } } public static void main(String[] args){ try { new App().showSearch("nihao"); } catch (InterruptedException e) { e.printStackTrace(); } } public void SystedisplayText(String str){ System.out.println("result="+str); } }
FutureTask类
FutureTask实现了Runnable, Future<V>, RunnableFuture<V> 接口,所以它既可以作为Runnable被线程执行,又可以作为Future得到Callable的返回值。
那么这个组合的使用有什么好处呢?假设有一个很耗时的返回值需要计算,并且这个返回值不是立刻需要的话,那么就可以使用FutureTask,用另一个线程去计算返回值,而当前线程在使用这个返回值之前可以做其他的操作,等到需要这个返回值时,再通过Future到的。
仅在计算完成时才能获取结果,如果计算尚未完成,则阻塞get方法,一旦计算完成,就不能再重新开始或者取消计算。
可以使用FutureTask包装Callable或者Runnable对象,因为FutureTask实现了Runnable,所以可以将FutureTask提交给Executor执行。

示例:
import java.util.Random; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; public class CallableAndFuture { public static void main(String[] args) { Callable<Integer> callable = new Callable<Integer>() { public Integer call() throws Exception { return new Random().nextInt(100); } }; FutureTask<Integer> future = new FutureTask<Integer>(callable); new Thread(future).start(); try { Thread.sleep(5000);// 可能做一些事情 System.out.println(future.get()); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } } }
现在我们不直接创建线程并开启线程,而是通过ExecutorService的submit方法执行Callable中的call():
public static void method(){ ExecutorService executorService=Executors.newSingleThreadExecutor(); Future<Integer> future=executorService.submit(new Callable<Integer>(){ @Override public Integer call() throws Exception { return new Random().nextInt(100); } }); try{ Thread.sleep(500);//doSomething System.out.println(""+future.get()); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } }
或是:
public static void method(){ FutureTask futureTask=new FutureTask(new Callable<Integer>(){ @Override public Integer call() throws Exception { return new Random().nextInt(100); } }); Executor executor=Executors.newSingleThreadExecutor(); executor.execute(futureTask); try{ Thread.sleep(500);//doSomething System.out.println(""+futureTask.get()); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } }

浙公网安备 33010602011771号