背景:在同步的web请求中,读取WebSocket 数据时,等待数据读取,并根据返回的结果,结束当前WebSocket连接。
CountDownLatch
是 Java 中用于线程间通信和同步的工具之一,它允许一个或多个线程等待其他线程完成操作后再继续执行。
利用 CountDownLatch
同步读取 WebSocket 数据的一般流程:
- 在主线程中初始化
CountDownLatch
对象,并指定等待的线程数量。 - 启动 WebSocket 客户端连接到 WebSocket 服务器。
- 启动一个单独的线程,用于读取 WebSocket 数据。
- 在读取数据的线程中,当接收到数据时,处理数据并调用
countDown()
方法来减少CountDownLatch
的计数器。 - 在主线程中,调用
await()
方法来阻塞等待,直到所有数据都被读取完毕,即CountDownLatch
的计数器减少到零。
这样可以确保在主线程中等待,直到所有的数据都被读取完毕,然后再继续执行其他操作。
java
Request wss = new Request.Builder()
.url(wss_url)
.build();
CountDownLatch latch = new CountDownLatch(1);
RespBean respBean = RespBean.build();
WebSocketListener listener = new WebSocketListener() {
@Override
public void onMessage(WebSocket webSocket, String text) {
super.onMessage(webSocket, text);
if (text.startsWith("{") && text.endsWith("}")) {
JSONObject rps = JSON.parseObject(text);
String body = rps.getString("body");
String bodyText = new String(Base64.getDecoder().decode(body));
String trim = bodyText.substring(5).trim();
if (trim.startsWith("{") && trim.endsWith("}")) {
JSONObject data = JSON.parseObject(trim);
JSONObject message = data.getJSONObject("message");
if (message != null) {
String status = message.getString("status");
if ("finished_successfully".equals(status)) {
respBean.setData(data);
webSocket.close(1000, "数据接受完成");
// 如果收到特定数据,则释放 CountDownLatch
latch.countDown();
}
}
} else if ("[DONE]".equals(trim)) {
webSocket.close(1000, "数据接受完成");
}
}
}
@Override
public void onMessage(WebSocket webSocket, ByteString bytes) {
super.onMessage(webSocket, bytes);
respBean.setData(bytes.hex());
System.out.println("Received bytes: " + bytes.hex());
}
@Override
public void onFailure(WebSocket webSocket, Throwable t, Response response) {
super.onFailure(webSocket, t, response);
respBean.setStatus(500);
respBean.setData(t);
t.printStackTrace();
}
};
RequestUtil.getOkHttpClient().newWebSocket(wss, listener);
try {
// 设置超时时间为30秒
if (!latch.await(60, TimeUnit.SECONDS)) {
// 超时未收到特定数据,进行处理
log.info("Timeout: Did not receive specific data within 60 seconds.");
} else {
// 收到特定数据,进行处理
log.info("Received specific data!");
}
} catch (InterruptedException e) {
log.error(e.getMessage());
}