第三部分-并发设计模式31:Guarded Suspension设计模式
1.Guarded Suspension设计模式
等待唤醒机制的规范实现
2.业务场景
用户发请求->异步消息->MQ->等MQ返回结果,结果返回浏览器
给mq发消息的线程是T1,但消费mq结果的线程不是T1,那么线程T1如何等待MQ的返回结果?
3.伪代码
class Message{
String id;
String content;
}
//该方法可以发送消息
void send(Message msg){
//省略相关代码
}
//MQ消息返回后会调用该方法
//该方法的执行线程不同于
//发送消息的线程
void onMessage(Message msg){
//省略相关代码
}
//处理浏览器发来的请求
Respond handleWebReq(){
//创建一消息
Message msg1 = new
Message("1","{...}");
//发送消息
send(msg1);
//如何等待MQ返回的消息呢?
String result = ...;
}
4.异步转同步
5.Guarder Suspension 套路
保护性暂停
示意图
对象GuardedObject,内部受保护成员变量,两个成员方法get(Predicate
对象GuardedObject好比大堂经理,受保护对象好比包间,get方法对应客户去就餐,就餐的前提是包间准备好,参数p就是来描述这个条件的
onChanged方法就是服务员把包间收拾好了,通过onChanged去fre一个事件,这个事件能改变p条件的计算结果。
6.Guarder Suspension 套路代码
class GuardedObject<T>{
//受保护的对象
T obj;
final Lock lock =
new ReentrantLock();
final Condition done =
lock.newCondition();
final int timeout=1;
//获取受保护对象
T get(Predicate<T> p) {
lock.lock();
try {
//MESA管程推荐写法
while(!p.test(obj)){
done.await(timeout,
TimeUnit.SECONDS);
}
}catch(InterruptedException e){
throw new RuntimeException(e);
}finally{
lock.unlock();
}
//返回非空的受保护对象
return obj;
}
//事件通知方法
void onChanged(T obj) {
lock.lock();
try {
this.obj = obj;
done.signalAll();
} finally {
lock.unlock();
}
}
}
7.如何使用
(1)GuardedObject对象,new一次,来回传递,方法级传递或线程之间的传递
(2)GuardedObject对象,get和消费的时候必须保证是同一个,如何在不同线程之间保证是一个GuardedObject对象,可以自定义一个对象,内嵌静态map,get和消费的时候,修改操作都从自定义的map中操作
范例自定义对象伪代码:
public class GuarderMap {
public static Map<Object,GuarderObject> map = Maps.newConcurrentMap();
public static void put(Object obj,GuarderObject g){
map.put(obj,g);
}
public static GuarderObject remove(Object obj){
return map.remove(obj);
}
}
范例操作
public class GuarderObject<T> {
T obj;
final Lock lock = new ReentrantLock();
final Condition condition = lock.newCondition();
final int timeOut = 3;
static <K> GuarderObject create(K key){
GuarderObject go = new GuarderObject();
GuarderMap.put(key, go);
return go;
}
static <K,T> void fireEvent(K key, T obj){
GuarderObject go = GuarderMap.remove(key);
Optional.ofNullable(go).ifPresent(g -> {
g.onChanged(obj);
});
}
void onChanged(T obj){
lock.lock();
try{
this.obj = obj;
condition.signalAll();
}finally {
lock.unlock();
}
}
T get(Predicate<T> p){
lock.lock();
try{
while (!p.test(obj)){
condition.await(timeOut, TimeUnit.SECONDS);
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
return obj;
}
public static void main(String[] args) {
GuarderObject<Message> go = GuarderObject.create("3");
// sendMq();
go.get(t->t != null);
// receive message
GuarderObject.fireEvent("3", "aaa");
}
}
8.Guarder Suspension
本质,等待唤醒机制的实现,只是规范化了,
原创:做时间的朋友
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 记一次.NET内存居高不下排查解决与启示