未来者设计模式(Future)
实现思路:将提交的任务交给新的线程执行,通过consumer消费者方式,将结果传递给回调方法,不影响主线的执行
优点:执行效率的增加
缺点:异步的方式,如果后面的代码需要结果,无法保证结果到达的事件
使用场景:客户去蛋糕店定制蛋糕,蛋糕店会给客户一个蛋糕券(凭证),客户就回去做自己的事情,蛋糕交给客户有两种方式:
- 客户没过一段时间就去问蛋糕店的蛋糕是否做好
- 蛋糕店做好后通知给客户去取,或者直接将蛋糕按预留的送货地址上门
定义接口,返回任意类型的结果
package com.ln.concurrent.chapter8;
/**
* @ProjectName: java-concurrency
* @Package: com.ln.concurrent.chapter8
* @Name:FutureTask
* @Author:linianest
* @CreateTime:2020/3/25 14:56
* @version:1.0
* @Description TODO:定义接口,返回任意类型的结果
*/
public interface Future<T> {
// 调用者调用的方法
T get() throws InterruptedException;
}
真正执行任务的接口,与返回者的返回值类型一样
/**
* @ProjectName: java-concurrency
* @Package: com.ln.concurrent.chapter8
* @Name:FutureTask
* @Author:linianest
* @CreateTime:2020/3/25 14:56
* @version:1.0
* @Description TODO:future 真正执行任务的接口
*/
public interface FutureTask<T> {
// 线程会掉返回结果的实现
T call();
}
实现Future接口:异步的方式实现思路
- 传参获取执行任务,获取到执行的任务后
- 新起一个线程执行任务,并把任务线程方法的线程阻塞住
- 当任务执行完成,唤醒任务线程,回调返回方法,获取执行结果
package com.ln.concurrent.chapter8;
/**
* @ProjectName: java-concurrency
* @Package: com.ln.concurrent.chapter8
* @Name:AsynFuture
* @Author:linianest
* @CreateTime:2020/3/25 15:04
* @version:1.0
* @Description TODO: 异步future实现
*/
public class AsynFuture<T> implements Future<T> {
private volatile boolean done = false;
private T result;
public void done(T result) {
synchronized (this) {
this.result = result;
this.done = true;
this.notifyAll();
}
}
@Override
public T get() throws InterruptedException {
synchronized (this) {
while (!done) {
this.wait();
}
}
return result;
}
}
实现连接future接口和future实现的接口
package com.ln.concurrent.chapter8;
import java.util.function.Consumer;
/**
* @ProjectName: java-concurrency
* @Package: com.ln.concurrent.chapter8
* @Name:FutureService
* @Author:linianest
* @CreateTime:2020/3/25 15:01
* @version:1.0
* @Description TODO: 实现连接future接口和future实现的接口
*/
public class FutureService {
// todo 被动模式:返回结果后,需要再次调用Future的get方法获取数据
public <T> Future<T> submit(final FutureTask<T> task) {
AsynFuture<T> asynFuture = new AsynFuture<>();
new Thread(() -> {
T result = task.call();
asynFuture.done(result);
}).start();
return asynFuture;
}
// todo 主动模式:任务执行完成后,将结果传递给给指定的方法
public <T> Future<T> submit(final FutureTask<T> task, final Consumer<T> consumer) {
AsynFuture<T> asynFuture = new AsynFuture<>();
new Thread(() -> {
T result = task.call();
// done方法时被动模式的,兼容的方式下,留着
// asynFuture.done(result);
consumer.accept(result);
}).start();
return asynFuture;
}
}
测试设计模式
package com.ln.concurrent.chapter8;
/**
* @ClassName:Synclovker
* @Author:linianest
* @CreateTime:2020/3/25 14:44
* @version:1.0
* @Description TODO: 同步(阻塞)调用
*/
/**
* Future -> 代表的是未来的一个凭据
* FutureTask -> 将你的调用逻辑进行了隔离
* FutureService ->桥接Future和FutureTask
*/
public class Synclnvoker {
public static void main(String[] args) throws InterruptedException {
// String result = get();
// System.out.println(result);
FutureService futureService = new FutureService();
Future<String> future = futureService.submit(() -> {
try {
Thread.sleep(10_000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "FINISH";
}, System.out::println);
System.out.println("================");
System.out.println("do other thing.");
Thread.sleep(1_000L);
System.out.println("================");
// System.out.println(future.get());
}
public static String get() throws InterruptedException {
Thread.sleep(10_000L);
return "FINISH";
}
}