Java并发编程:Callable、Future、FutureTask的使用
整理自:博客园-海子-http://www.cnblogs.com/dolphin0520/p/3949310.html
继承关系:
1、接口Callable与Runnable
1.1、Runnable接口中只有一个void run()方法,其返回值是void,执行完任务后,无法返回任何结果(只能通过操作共享变量);
1.2、Callable接口位于java.util.concurrent包下,只有一个V call() throws Exception方法,返回一个输入类型V;
Callable需要配合ExecutorService来使用,其中声明了若干个submit方法,以下两种最常用:
<T> Future<T> submit(Callable<T> task);
Future<?> submit(Runnable task);
2、接口Future:
表示具体的Runnable或者Callable任务的具体的执行结果,
通过以下五种方法,实现任务的中断、是否完成、获取结果。
boolean cancel(boolean mayInterruptIfRunning):试图取消对此任务的 执行:参数为true表示可以打断正在执行的任务。 返回false:任务已经完成;任务未完成参数为true; 返回true:任务未开始;任务未完成参数为false; isCancelled():如果在任务正常完成前将其取消,则返回 true。。 isDone():方法表示任务是否已经完成,若任务完成,则返回true get():等待计算完成返回V; get(long timeout, TimeUnit unit):最多等待timeout时间,若结果可用返回。
3、类FutureTask:
FutureTask实现了Future和Runnable接口,有两种构造器:
public FutureTask(Callable<V> callable) { } public FutureTask(Runnable runnable, V result) { }
实例代码:
1、使用Callable和Future获取结果:
//使用Callable和Future获取执行结果; public class Test { public static void main (String[] args){ ExecutorService executor = Executors.newCachedThreadPool(); Task task = new Task(); Future<Integer> result = executor.submit(task); executor.shutdown(); try { Thread.sleep(1000); } catch (InterruptedException e1) { e1.printStackTrace(); } System.out.println("主线程在执行任务"); try { System.out.println("task运行结果"+result.get()); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } System.out.println("所有任务执行完毕"); } } class Task implements Callable<Integer>{ @Override public Integer call() throws Exception { System.out.println("子线程在进行计算"); Thread.sleep(3000); int sum = 0; for(int i=0;i<100;i++) sum += i; return sum; } }
子线程在进行计算
主线程在执行任务
task运行结果4950
所有任务执行完毕
2、使用Callable+FutureTask获取执行结果:
public class Test { public static void main(String[] args) { //第一种方式 ExecutorService executor = Executors.newCachedThreadPool(); Task task = new Task(); FutureTask<Integer> futureTask = new FutureTask<Integer>(task); executor.submit(futureTask); executor.shutdown(); //第二种方式,注意这种方式和第一种方式效果是类似的,只不过一个使用的是ExecutorService,一个使用的是Thread /*Task task = new Task(); FutureTask<Integer> futureTask = new FutureTask<Integer>(task); Thread thread = new Thread(futureTask); thread.start();*/ try { Thread.sleep(1000); } catch (InterruptedException e1) { e1.printStackTrace(); } System.out.println("主线程在执行任务"); try { System.out.println("task运行结果"+futureTask.get()); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } System.out.println("所有任务执行完毕"); } } class Task implements Callable<Integer>{ @Override public Integer call() throws Exception { System.out.println("子线程在进行计算"); Thread.sleep(3000); int sum = 0; for(int i=0;i<100;i++) sum += i; return sum; } }
子线程在进行计算
主线程在执行任务
task运行结果4950
所有任务执行完毕