- Java多線程編程實戰指南:設計模式篇(第2版)
- 黃文海
- 862字
- 2021-10-15 19:24:57
4.3 Guarded Suspension模式實戰案例解析
某系統有一個告警[2]功能模塊。該模塊的主要功能是將其接收到的告警信息發送給告警服務器。該模塊中的類AlarmAgent負責與告警服務器進行對接。AlarmAgent的sendAlarm方法負責通過網絡連接(Socket連接)將告警信息發送給告警服務器。AlarmAgent創建了一個專門的線程用于其與告警服務器建立網絡連接。因此,在sendAlarm方法被調用的時候,連接線程可能還沒有完成網絡連接的建立。此時,sendAlarm方法應該等待連接線程建立好網絡連接。另外,即便連接線程建立好了網絡連接,中途也可能由于某些原因出現與告警服務器斷連的情況。此時,sendAlarm方法需要等待心跳(Heartbeat)任務[3]重新建立好連接后,才能上報告警信息。也就是說,sendAlarm方法必須在AlarmAgent與告警服務器的網絡連接建立成功的情況下才能執行其所要執行的操作。若AlarmAgent與告警服務器的連接未建立(或者連接中斷),sendAlarm方法的執行線程應該被暫掛直到連接建立完畢(或者恢復)。
上述問題可以應用Guarded Suspension模式來解決,如清單4-1所示。
清單4-1 AlarmAgent類源代碼



如清單4-1所示代碼中的sendAlarm方法,會等待其所屬的AlarmAgent實例連接上告警服務器后才調用doSendAlarm方法來真正地將告警信息上報給告警服務器。若在sendAlarm方法被調用時AlarmAgent實例與告警服務器的連接未建立完畢或者連接中斷了,則sendAlarm方法會使當前線程阻塞,直到其他線程喚醒該被阻塞的線程且AlarmAgent實例與告警服務器的連接建立完畢。可見,AlarmAgent實例相當于Guarded Suspension模式中的GuardedObject參與者實例,其sendAlarm方法是一個受保護方法。sendAlarm方法的目標動作是doSendAlarm所執行的操作(上報告警信息給告警服務器)。sendAlarm方法的保護條件是AlarmAgent實例與告警服務器已建立網絡連接(即connectedToServer的值為true)。
AlarmAgent的實例變量agentConnected相當于Predicate參與者實例。AlarmAgent的實例變量blocker相當于Blocker參與者實例。
AlarmAgent的onConnected方法相當于GuardedObject參與者的stateChanged方法。當告警服務器連接線程建立起與告警服務器的連接,或者心跳定時任務在網絡連接中斷后重新連接完畢時,onConnected方法都會被調用。此時,onConnected方法通過調用Blocker的實例blocker的signalAfter方法[4],將標志變量connectedToServer設置為true,并“通知”blocker去喚醒被暫掛的sendAlarm方法去執行線程。
清單4-1中的代碼所引用的其他類的源代碼,如清單4-2、清單4-3、清單4-4和清單4-5所示。
清單4-2 Predicate接口源代碼

清單4-3 GuardedAction類源代碼

清單4-4 Blocker接口源代碼

清單4-5 ConditionVarBlocker類源代碼



- UI圖標創意設計
- ASP.NET Core:Cloud-ready,Enterprise Web Application Development
- Qt 5 and OpenCV 4 Computer Vision Projects
- Apache ZooKeeper Essentials
- Python for Secret Agents:Volume II
- Mastering Scientific Computing with R
- Linux命令行與shell腳本編程大全(第4版)
- Unity Game Development Scripting
- UML 基礎與 Rose 建模案例(第3版)
- 深入分布式緩存:從原理到實踐
- Go語言精進之路:從新手到高手的編程思想、方法和技巧(1)
- Learning AngularJS for .NET Developers
- HTML5權威指南
- Java Web從入門到精通(第2版)
- PyQt編程快速上手