1. FutureTask简介
FutureTask除了实现Future接口外,还实现了Runnable接口。因此,FutureTask可以交给Executor执行,也可以由调用线程直接执行(FutureTask.run())。
根据FutureTask.run()方法被执行的时机,FutureTask可以处于下面3种状态。
未启动。FutureTask.run()方法还没有被执行之前,FutureTask处于未启动状态。当创建一个FutureTask,且没有执行FutureTask.run()方法之前,这个FutureTask处于未启动状态。
已启动。FutureTask.run()方法被执行的过程中,FutureTask处于已启动状态。
已完成。FutureTask.run()方法执行完后正常结束,或被取消(FutureTask.cancel(…)),或执行FutureTask.run()方法时抛出异常而异常结束,FutureTask处于已完成状态。
2. FutureTask状态迁移
2.1 get和cancel使用介绍
- 当FutureTask处于未启动或已启动状态时,执行FutureTask.get()方法将导致调用线程阻塞;
- 当FutureTask处于已完成状态时,执行FutureTask.get()方法将导致调用线程立即返回结果或抛出异常。
- 当FutureTask处于未启动状态时,执行FutureTask.cancel()方法将导致此任务永远不会被执行;
- 当FutureTask处于已启动状态时,执行FutureTask.cancel(true)方法将以中断执行此任务线程的方式来试图停止任务;
- 当FutureTask处于已启动状态时,执行FutureTask. cancel(false)方法将不会对正在执行此任务的线程产生影响(让正在执行的任务运行完成);
- 当FutureTask处于已完成状态时,执行FutureTask.cancel(…)方法将返回false。
以上内容摘自《Java并发的艺术》第十章第四节 FutureTask详情 片段。
3. FutureTask使用
3.1 计算1~10阶乘的和
10! + 9! + ...+1! = ?
阶乘的概念:
3.2 futureTask实现
package com.hui.javalearn.thread.futureTask;
import java.util.ArrayList; import java.util.concurrent.*;
public class FutureTaskTest {
public void testTask() { long beginTime = System.currentTimeMillis(); FutureTaskTest futureTaskTest = new FutureTaskTest();
ArrayList<FutureTask<Integer>> futureTaskList = new ArrayList<>(); ExecutorService executorService = Executors.newFixedThreadPool(10); for (int i = 1; i <= 10; i++) { FutureTask<Integer> futureTask = new FutureTask<>(futureTaskTest.new ComputerTask(i)); futureTaskList.add(futureTask); executorService.submit(futureTask); }
System.out.println("任务已经提交完,主线程继续执行...."); ArrayList<Integer> taskResultList = new ArrayList<>(); for (FutureTask<Integer> futureTaskItem : futureTaskList) { try { Integer total = futureTaskItem.get(); taskResultList.add(total); } catch (ExecutionException | InterruptedException e) { e.printStackTrace(); } } Integer integer = taskResultList.stream().reduce(Integer::sum).get(); long useTime = (System.currentTimeMillis() - beginTime) / 1000L; System.out.println("10! + 9! + ...+1! = " + integer ); System.out.println(" 一共耗时:" + useTime + "秒");
executorService.shutdown(); System.out.println("任务执行完毕。");
}
private class ComputerTask implements Callable<Integer> { private Integer num; private Integer total;
ComputerTask(Integer i) { this.num = i; }
@Override public Integer call() throws Exception { total = 1; String s =""; for (int i = 1; i <= this.num; i++) { total *= i; s = s.concat(String.valueOf(i)).concat(" * "); } String substring = s.substring(0,s.length()-2); Thread.sleep(1000); System.out.println(substring + " = " + total); return total; } } }
...
new FutureTaskTest().testTask();
|
3.2 串行实现
package com.hui.javalearn.thread.futureTask;
import java.util.ArrayList; import java.util.concurrent.*;
public class FutureTaskTest {
private class ComputerTask implements Callable<Integer> { private Integer num; private Integer total;
ComputerTask(Integer i) { this.num = i; }
@Override public Integer call() throws Exception { total = 1; String s =""; for (int i = 1; i <= this.num; i++) { total *= i; s = s.concat(String.valueOf(i)).concat(" * "); } String substring = s.substring(0,s.length()-2); Thread.sleep(1000); System.out.println(substring + " = " + total); return total; } }
public void testSerialTask() throws Exception { long beginTime = System.currentTimeMillis(); FutureTaskTest futureTaskTest = new FutureTaskTest(); ArrayList<Integer> taskResultList = new ArrayList<>(); for (int i = 1; i <= 10; i++) { Integer call = futureTaskTest.new ComputerTask(i).call(); taskResultList.add(call); } Integer integer = taskResultList.stream().reduce(Integer::sum).get(); long useTime = (System.currentTimeMillis() - beginTime) / 1000L; System.out.println("10! + 9! + ...+1! = " + integer ); System.out.println("一共耗时:" + useTime + "秒");
} }
...
|
查看源码
4.参考链接