Promise 模式
简介
Promise 模式是一种异步编程模式,使用它我们可以先开始一个任务, 并能立即获取这个任务的执行结果的凭证对象, 而不需要等待任务执行完毕,就可以继续执行其他操作. 当需要执行结果的时候,可以通过凭证对象,可以调用相应方法来获取.
这样操作的好处就是: 避免了不必要的等待, 增强系统的并发性.
成员
- 任务执行器
- 凭证对象
- 自定义任务
- 任务结果对象
实例实现
- 模拟任务 - MyTask
public class MyTask implements Callable<MyPromiseResult> {
private String context;
public MyTask(String context) {
this.context = context;
}
@Override
public MyPromiseResult call() throws Exception {
Random random = new Random();
int workTime = random.nextInt(5 * 1000);
MyPromiseResult result = new MyPromiseResult(workTime, context);
result.setTaskStartTime();
Thread.sleep(workTime);// 模拟工作
result.setTaskEndTime();
return result;
}
}
- 凭证对象使用: FutureTask
- 凭证返回结果: MyPromiseResult
public class MyPromiseResult {
// 任务开始时间
private long taskStartTime;
// 任务结束时间
private long taskEndTime;
// 工作耗时间
private final int workTime;
// 上下文任务名称
private final String taskName ;
public MyPromiseResult (int workTime, final String taskName) {
this.workTime = workTime;
this.taskName = taskName;
}
public void setTaskStartTime() {
this.taskStartTime = System.currentTimeMillis();
}
public void setTaskEndTime() {
this.taskEndTime = System.currentTimeMillis();
}
public long getTaskStartTime() {
return this.taskStartTime;
}
public long getTaskEndTime() {
return this.taskEndTime;
}
public String getTaskName() {
return taskName;
}
public void print() {
if (taskEndTime > 0) { // 代表完成
System.out.println("完成任务名称:" + taskName +"...开始时间" + taskStartTime +"...耗时间:"
+ workTime);
}
}
}
- 测试类
public class PromiseTester {
// 任务执行器
static ThreadPoolExecutor threadExecutor = null;
static {
threadExecutor = new ThreadPoolExecutor(2, Runtime.getRuntime().availableProcessors() * 2 ,
60, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(10),
new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setDaemon(true);
return t;
}
});
}
public static void main(String args[]) throws InterruptedException, ExecutionException {
test();
}
/**
*
* 测试有一个任务它由10个子任务构成, 每个子任务相互独立
* 只有10个子任务都完成,这个任务才算完成
* @throws InterruptedException
* @throws ExecutionException
*/
public static void test() throws InterruptedException, ExecutionException {
ConcurrentMap<String, FutureTask<MyPromiseResult>> taskMap = new ConcurrentHashMap<String,
FutureTask<MyPromiseResult>>();
for (int i = 0; i < 10; i ++) {
String name = "task-" + i;
FutureTask<MyPromiseResult> futureTask = PromiseTester.execute(name);
taskMap.put(name, futureTask);
}
FutureTask<MyPromiseResult> task = null;
MyPromiseResult myPromiseResult;
// 轮询判断任务是否完成
for (;;) {
if (!taskMap.isEmpty()) {
Iterator<String> iterator = taskMap.keySet().iterator();
while (iterator.hasNext()) {
task = taskMap.get(iterator.next());
if (null != task && task.isDone()) {
myPromiseResult = task.get();
myPromiseResult.print();
taskMap.remove(myPromiseResult.getTaskName());
iterator = taskMap.keySet().iterator();
}
}
} else {
break;
}
Thread.sleep(10);
}
System.out.println("############所有任务完成###############");
}
/**
* 异步提交,并获取凭证对象
*
* @param context
* @return
*/
public static FutureTask<MyPromiseResult> execute(String context) {
FutureTask<MyPromiseResult> futureTask = new FutureTask<MyPromiseResult>(new MyTask(context));
threadExecutor.execute(futureTask);
return futureTask;
}
}
- 测试结果
完成任务名称:task-0...开始时间1471786979890...耗时间:352
完成任务名称:task-1...开始时间1471786979890...耗时间:1526
完成任务名称:task-3...开始时间1471786981416...耗时间:1835
完成任务名称:task-2...开始时间1471786980242...耗时间:4534
完成任务名称:task-4...开始时间1471786983251...耗时间:3672
完成任务名称:task-5...开始时间1471786984776...耗时间:3908
完成任务名称:task-6...开始时间1471786986923...耗时间:2037
完成任务名称:task-7...开始时间1471786988684...耗时间:2948
完成任务名称:task-9...开始时间1471786991632...耗时间:238
完成任务名称:task-8...开始时间1471786988960...耗时间:3923
############所有任务完成###############