Google Guava 工具類(一)—— EventBus(觀察者模式的實作)
??? 未解決的問題:
AsyncEventBus的并發執行
EventBus 是設計模式中的觀察者模式(生產者/消費者編程模型)的實作,
在學習 EventBus 之前,先了解一下其涉及到的相關術語
EvenBus 中的相關術語
| EventBus 術語 | 解釋 | 備注 |
|---|---|---|
| 事件(訊息) | 可以向事件總線(EventBus)發布的物件 | 通常是一個類,不同的訊息事件用不同的類來代替,訊息內容就是類里面的屬性 |
| 訂閱 | 向事件總線注冊監聽者,以接受事件的行為 | EventBus.register(Object),引數就是監聽者 |
| 監聽者 | 提供一個處理方法,希望接受和處理事件的物件 | 通常也是一個類,里面有訊息的處理方法 |
| 處理方法 | 監聽者提供的公共方法,事件總線使用該方法向監聽者發送事件;該方法應使用 Subscribe 注解 | 監聽者里面添加一個 Subscribe 注解的方法,就可以認為是訊息的處理方法 |
| 發布訊息 | 通過事件總線向所有匹配的監聽者提供事件 | EventBus.post(Object) |
EvenBus 的簡單使用
添加依賴
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>31.1-jre</version>
</dependency>
EventBus 的使用很簡單,籠統來說可分為以下幾個步驟,
- 創建 EventBus 物件,通常全域或模塊內通過單例模式只用一個 EventBus 物件
- 創建訊息類
- 創建監聽者類
- 注冊監聽者類,如果有多個 EventBus 物件,監聽者類注冊在哪個 EventBus 物件下,訊息就需要發布到對應的 EventBus 中
- 發布訊息
EventBusDemo.java
package cn.jkingtools.demo.guava.eventbus;
import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.Subscribe;
public class EventBusDemo {
// 1. 創建訊息類
private static class Message {
private String message;
public Message(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
// 2. 創建監聽者類,即事件處理函式,需要使用 @Subscribe 進行注解
private static class EventListener {
@Subscribe
public void dealWithEvent(Message msg) {
System.out.println("接收訊息" + msg.getMessage());
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("處理訊息" + msg.getMessage());
}
}
public static void main(String[] args) {
// 3. 創建 EventBus 物件
EventBus eventBus = new EventBus("Test");
// 4. 注冊監聽者類
eventBus.register(new EventListener());
// 5. 發布訊息
for (int i=0; i<5; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("---------");
eventBus.post(new Message("tttt" + i));
}
}
}
執行輸出資訊:
---------
接收訊息tttt0
處理訊息tttt0
---------
接收訊息tttt1
處理訊息tttt1
---------
接收訊息tttt2
處理訊息tttt2
---------
接收訊息tttt3
處理訊息tttt3
---------
接收訊息tttt4
處理訊息tttt4
在上面的代碼中,添加了幾個 sleep,在實際運行的時候注意輸出,所有的事件訊息都是順序輸出的,這是因為事件的發送方和事件消費方都在一個執行緒中,事件發送方只有在發送的事件處理完畢后才會繼續執行自己后面的代碼,這里可使用 AsyncEventBus 類實作事件的異步處理,也就是將事件處理放到一個執行緒池里面去執行,
AsyncEventBus(EventBus 的異步實作)
com.google.common.eventbus.AsyncEventBus 是 EventBus 的異步實作,即將事件放到一個單獨的執行緒池中去執行,只需要將實體化的 EventBus 物件換成 AsyncEventBus 即可,并傳入一個執行緒池物件,
AsyncEventBus asyncEventBus = new AsyncEventBus("", Executors.newCachedThreadPool());
??? 我的測驗原始碼如下,但未實作事件的并行執行,
package cn.jkingtools.demo.guava.eventbus; import com.google.common.eventbus.AsyncEventBus; import com.google.common.eventbus.EventBus; import com.google.common.eventbus.Subscribe; import java.util.concurrent.Executors; public class AsyncEventBusDemo { // 1. 創建訊息類 private static class Message { private String message; public Message(String message) { this.message = message; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } } // 2. 創建監聽者類,即事件處理函式,需要使用 @Subscribe 進行注解 private static class EventListener { @Subscribe public void dealWithEvent(Message msg) { System.out.println("接收訊息" + msg.getMessage()); try { Thread.sleep(10000); } catch (InterruptedException e) { throw new RuntimeException(e); } System.out.println("處理訊息" + msg.getMessage()); } } public static void main(String[] args) { // 3. 創建 EventBus 物件 AsyncEventBus eventBus = new AsyncEventBus("Test", Executors.newCachedThreadPool()); // 4. 注冊監聽者類 eventBus.register(new EventListener()); // 5. 發布訊息 for (int i=0; i<10; i++) { try { Thread.sleep(1000); } catch (InterruptedException e) { throw new RuntimeException(e); } System.out.println("---------"); eventBus.post(new Message("tttt" + i)); } } }輸出資訊如下:
--------- 接收訊息tttt0 --------- --------- --------- --------- 處理訊息tttt0 接收訊息tttt4 處理訊息tttt4 接收訊息tttt3 處理訊息tttt3 接收訊息tttt2 處理訊息tttt2 接收訊息tttt1 處理訊息tttt1通過觀察輸出,AsyncEventBus 雖然并未在主執行緒阻塞,但事件卻是被順序執行的,并未實作并發,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/524863.html
標籤:Java
