Java并发编程实战~Guarded Suspension模式
Guarded Suspension 模式
????????比如,項目組團建要外出聚餐,我們提前預訂了一個包間,然后興沖沖地奔過去,到那兒后大堂經(jīng)理看了一眼包間,發(fā)現(xiàn)服務員正在收拾,就會告訴我們:“您預訂的包間服務員正在收拾,請您稍等片刻。”過了一會,大堂經(jīng)理發(fā)現(xiàn)包間已經(jīng)收拾完了,于是馬上帶我們去包間就餐。
????????那我們來看看現(xiàn)實世界里是如何解決這類問題的呢?現(xiàn)實世界里大堂經(jīng)理這個角色很重要,我們是否等待,完全是由他來協(xié)調的。通過類比,相信你也一定有思路了:我們的程序里,也需要這樣一個大堂經(jīng)理。的確是這樣,那程序世界里的大堂經(jīng)理該如何設計呢?其實設計方案前人早就搞定了,而且還將其總結成了一個設計模式:Guarded Suspension。所謂Guarded Suspension,直譯過來就是“保護性地暫停”。
class GuardedObject<T>{// 受保護的對象private T obj;final Lock lock = new ReentrantLock();final Condition done = lock.newCondition();final int timeout=1;// 獲取受保護對象 public 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;}// 事件通知方法public void onChanged(T obj) {lock.lock();try {this.obj = obj;done.signalAll();} finally {lock.unlock();}} }擴展 Guarded Suspension 模式
????????每個發(fā)送到 MQ 的消息,都有一個唯一性的屬性 id,所以我們可以維護一個 MQ 消息 id 和GuardedObject 對象實例的關系,這個關系可以類比大堂經(jīng)理大腦里維護的包間和就餐人的關系。
class GuardedObject<T>{// 受保護的對象T obj;final Lock lock = new ReentrantLock();final Condition done = lock.newCondition();final int timeout=2;// 保存所有 GuardedObjectfinal static Map<Object, GuardedObject> gos = new ConcurrentHashMap<>();// 靜態(tài)方法創(chuàng)建 GuardedObjectpublic static <K> GuardedObject create(K key){GuardedObject go=new GuardedObject();gos.put(key, go);return go;}public static <K, T> void fireEvent(K key, T obj){GuardedObject go=gos.remove(key);if (go != null){go.onChanged(obj);}}// 獲取受保護對象 public 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();}} }利用擴展后的 GuardedObject 來解決消息反饋后處理很簡單了
// 處理瀏覽器發(fā)來的請求 Respond handleWebReq(){int id= 序號生成器.get();// 創(chuàng)建一消息Message msg1 = new Message(id,"{...}");// 創(chuàng)建 GuardedObject 實例GuardedObject<Message> go= GuardedObject.create(id); // 發(fā)送消息send(msg1);// 等待 MQ 消息Message r = go.get(t->t != null); }void onMessage(Message msg){// 喚醒等待的線程GuardedObject.fireEvent(msg.id, msg); }總結
以上是生活随笔為你收集整理的Java并发编程实战~Guarded Suspension模式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Spring Data JPA 从入门到
- 下一篇: 线程Blocked--Synchroni