日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

java异步处理同步化_java 异步查询转同步多种实现方式:循环等待,CountDownLatch,Spring Even...

發布時間:2025/3/19 javascript 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java异步处理同步化_java 异步查询转同步多种实现方式:循环等待,CountDownLatch,Spring Even... 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

異步轉同步

業務需求

有些接口查詢反饋結果是異步返回的,無法立刻獲取查詢結果。

正常處理邏輯

觸發異步操作,然后傳遞一個唯一標識。

等到異步結果返回,根據傳入的唯一標識,匹配此次結果。

如何轉換為同步

正常的應用場景很多,但是有時候不想做數據存儲,只是想簡單獲取調用結果。

即想達到同步操作的結果,怎么辦呢?

思路

發起異步操作

在異步結果返回之前,一直等待(可以設置超時)

結果返回之后,異步操作結果統一返回

循環等待

LoopQuery.java

使用 query(),將異步的操作 remoteCallback() 執行完成后,同步返回。

public class LoopQuery implements Async {

private String result;

private static final Logger LOGGER = LogManager.getLogger(LoopQuery.class.getName());

@Override

public String query(String key) {

startQuery(key);

new Thread(new Runnable() {

@Override

public void run() {

remoteCallback(key);

}

}).start();

final String queryResult = endQuery();

LOGGER.info("查詢結果: {}", queryResult);

return queryResult;

}

/**

* 開始查詢

* @param key 查詢條件

*/

private void startQuery(final String key) {

LOGGER.info("執行查詢: {}", key);

}

/**

* 遠程的回調是等待是隨機的

*

* @param key 查詢條件

*/

private void remoteCallback(final String key) {

try {

TimeUnit.SECONDS.sleep(5);

} catch (InterruptedException e) {

e.printStackTrace();

}

this.result = key + "-result";

LOGGER.info("remoteCallback set result: {}", result);

}

/**

* 結束查詢

* @return 返回結果

*/

private String endQuery() {

while (true) {

if (null == result) {

try {

TimeUnit.MILLISECONDS.sleep(100);

} catch (InterruptedException e) {

e.printStackTrace();

}

} else {

return result;

}

}

}

}

main()

public static void main(String[] args) {

new LoopQuery().query("12345");

}

測試結果

18:14:16.491 [main] INFO com.github.houbb.thread.learn.aysnc.loop.LoopQuery - 執行查詢: 12345

18:14:21.498 [Thread-1] INFO com.github.houbb.thread.learn.aysnc.loop.LoopQuery - remoteCallback set result: 12345-result

18:14:21.548 [main] INFO com.github.houbb.thread.learn.aysnc.loop.LoopQuery - 查詢結果: 12345-result

CountDownLatch

AsyncQuery.java

使用 CountDownLatch 類達到同步的效果。

import org.apache.logging.log4j.LogManager;

import org.apache.logging.log4j.Logger;

import java.util.concurrent.CountDownLatch;

import java.util.concurrent.TimeUnit;

public class AsyncQuery {

private static final Logger LOGGER = LogManager.getLogger(AsyncQuery.class.getName());

/**

* 結果

*/

private String result;

/**

* 異步轉同步查詢

* @param key

*/

public void asyncQuery(final String key) {

final CountDownLatch latch = new CountDownLatch(1);

this.startQuery(key);

new Thread(new Runnable() {

@Override

public void run() {

LOGGER.info("遠程回調線程開始");

remoteCallback(key, latch);

LOGGER.info("遠程回調線程結束");

}

}).start();

try {

latch.await();

} catch (InterruptedException e) {

e.printStackTrace();

}

this.endQuery();

}

private void startQuery(final String key) {

LOGGER.info("執行查詢: {}", key);

}

/**

* 遠程的回調是等待是隨機的

* @param key

*/

private void remoteCallback(final String key, CountDownLatch latch) {

try {

TimeUnit.SECONDS.sleep(5);

} catch (InterruptedException e) {

e.printStackTrace();

}

this.result = key + "-result";

latch.countDown();

}

private void endQuery() {

LOGGER.info("查詢結果: {}", result);

}

}

main()

public static void main(String[] args) {

AsyncQuery asyncQuery = new AsyncQuery();

final String key = "123456";

asyncQuery.asyncQuery(key);

}

日志

18:19:12.714 [main] INFO com.github.houbb.thread.learn.aysnc.countdownlatch.AsyncQuery - 執行查詢: 123456

18:19:12.716 [Thread-1] INFO com.github.houbb.thread.learn.aysnc.countdownlatch.AsyncQuery - 遠程回調線程開始

18:19:17.720 [main] INFO com.github.houbb.thread.learn.aysnc.countdownlatch.AsyncQuery - 查詢結果: 123456-result

18:19:17.720 [Thread-1] INFO com.github.houbb.thread.learn.aysnc.countdownlatch.AsyncQuery - 遠程回調線程結束

Spring EventListener

使用觀察者模式也可以。(對方案一的優化)

此處結合 spring 進行使用。

BookingCreatedEvent.java

定義一個傳輸屬性的對象。

public class BookingCreatedEvent extends ApplicationEvent {

private static final long serialVersionUID = -1387078212317348344L;

private String info;

public BookingCreatedEvent(Object source) {

super(source);

}

public BookingCreatedEvent(Object source, String info) {

super(source);

this.info = info;

}

public String getInfo() {

return info;

}

}

BookingService.java

說明:當 this.context.publishEvent(bookingCreatedEvent); 觸發時,

會被 @EventListener 指定的方法監聽到。

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.context.ApplicationContext;

import org.springframework.context.event.EventListener;

import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

@Service

public class BookingService {

@Autowired

private ApplicationContext context;

private volatile BookingCreatedEvent bookingCreatedEvent;

/**

* 異步轉同步查詢

* @param info

* @return

*/

public String asyncQuery(final String info) {

query(info);

new Thread(new Runnable() {

@Override

public void run() {

remoteCallback(info);

}

}).start();

while(bookingCreatedEvent == null) {

//.. 空循環

// 短暫等待。

try {

TimeUnit.MILLISECONDS.sleep(1);

} catch (InterruptedException e) {

//...

}

//2. 使用兩個單獨的 event...

}

final String result = bookingCreatedEvent.getInfo();

bookingCreatedEvent = null;

return result;

}

@EventListener

public void onApplicationEvent(BookingCreatedEvent bookingCreatedEvent) {

System.out.println("監聽到遠程的信息: " + bookingCreatedEvent.getInfo());

this.bookingCreatedEvent = bookingCreatedEvent;

System.out.println("監聽到遠程消息后: " + this.bookingCreatedEvent.getInfo());

}

/**

* 執行查詢

* @param info

*/

public void query(final String info) {

System.out.println("開始查詢: " + info);

}

/**

* 遠程回調

* @param info

*/

public void remoteCallback(final String info) {

System.out.println("遠程回調開始: " + info);

try {

TimeUnit.SECONDS.sleep(2);

} catch (InterruptedException e) {

e.printStackTrace();

}

// 重發結果事件

String result = info + "-result";

BookingCreatedEvent bookingCreatedEvent = new BookingCreatedEvent(this, result);

//觸發event

this.context.publishEvent(bookingCreatedEvent);

}

}

測試方法

@RunWith(SpringJUnit4Cla***unner.class)

@ContextConfiguration(classes = SpringConfig.class)

public class BookServiceTest {

@Autowired

private BookingService bookingService;

@Test

public void asyncQueryTest() {

bookingService.asyncQuery("1234");

}

}

日志

2018-08-10 18:27:05.958 INFO [main] com.github.houbb.spring.lean.core.ioc.event.BookingService:84 - 開始查詢:1234

2018-08-10 18:27:05.959 INFO [Thread-2] com.github.houbb.spring.lean.core.ioc.event.BookingService:93 - 遠程回調開始:1234

接收到信息: 1234-result

2018-08-10 18:27:07.964 INFO [Thread-2] com.github.houbb.spring.lean.core.ioc.event.BookingService:73 - 監聽到遠程的信息: 1234-result

2018-08-10 18:27:07.964 INFO [Thread-2] com.github.houbb.spring.lean.core.ioc.event.BookingService:75 - 監聽到遠程消息后: 1234-result

2018-08-10 18:27:07.964 INFO [Thread-2] com.github.houbb.spring.lean.core.ioc.event.BookingService:106 - 已經觸發event

2018-08-10 18:27:07.964 INFO [main] com.github.houbb.spring.lean.core.ioc.event.BookingService:67 - 查詢結果: 1234-result

2018-08-10 18:27:07.968 INFO [Thread-1] org.springframework.context.support.GenericApplicationContext:993 - Closing org.springframework.context.support.GenericApplicationContext@5cee5251: startup date [Fri Aug 10 18:27:05 CST 2018]; root of context hierarchy

超時和空循環

空循環

空循環會導致 cpu 飆升

while(true) {

}

解決方式

while(true) {

// 小睡即可

TimeUnit.sleep(1);

}

超時編寫

不可能一直等待反饋,可以設置超時時間。

/**

* 循環等待直到獲取結果

* @param key key

* @param timeoutInSeconds 超時時間

* @param 泛型

* @return 結果。如果超時則拋出異常

*/

public T loopWaitForValue(final String key, long timeoutInSeconds) {

long startTime = System.nanoTime();

long deadline = startTime + TimeUnit.SECONDS.toNanos(timeoutInSeconds);

//1. 如果沒有新回調,或者 key 對應元素不存在。則一直循環

while(ObjectUtil.isNull(map.get(key))) {

try {

TimeUnit.MILLISECONDS.sleep(5);

} catch (InterruptedException e) {

LOGGER.warn("Loop meet InterruptedException, just ignore it.", e);

}

// 超時判斷

long currentTime = System.nanoTime();

if(currentTime >= deadline) {

throw new BussinessException(ErrorCode.READ_TIME_OUT);

}

}

final T target = (T) map.get(key);

LOGGER.debug("loopWaitForValue get value:{} for key:{}", JSON.toJSON(target), key);

//2. 獲取到元素之后,需要移除掉對應的值

map.remove(key);

return target;

}

代碼地址

總結

以上是生活随笔為你收集整理的java异步处理同步化_java 异步查询转同步多种实现方式:循环等待,CountDownLatch,Spring Even...的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 性猛交xxxx| 日韩黄色在线视频 | 欧美老少做受xxxx高潮 | 99草| 久操不卡 | 两性囗交做爰视频 | 涩涩在线播放 | 三级大片在线观看 | youjizz麻豆 | 欧美日韩色图片 | 欧美黑人一级 | 亚洲性图第一页 | 超碰在线看 | 亚洲一区二区中文字幕 | 久久久精品免费看 | 久久久精品电影 | 日韩美女爱爱 | 黄色免费在线观看视频 | 一区二区三区亚洲 | 成人黄网免费观看视频 | 91本色| 欧美高清hd | 乱熟女高潮一区二区在线 | 欧美做爰全过程免费看 | 99国产精品欲 | 中文字幕在线二区 | 日韩一区二区视频在线播放 | 国产欧美二区 | 精品国产美女 | 亚洲hhh| 欧美精品久久久久久久多人混战 | 国产精品无码av在线有声小说 | av免费网 | 亚洲黄网在线观看 | 黄色一级片免费播放 | 亚州av综合色区无码一区 | 91中出 | 成人黄色性视频 | 亚洲精品成人网 | 91视频黄色 | 免费污视频在线观看 | 超碰午夜 | 日韩国产在线一区 | 国产精品黄色在线观看 | 狂野少女电影在线观看国语版免费 | 性爱视频在线免费 | 国产又粗又猛又爽免费视频 | 国产精品伦理 | 国产成人在线电影 | 欧美黑人一级 | 日韩精品免费在线观看 | 欧美日韩国产在线 | 久久国产劲爆∧v内射 | 欧美精品二区三区四区免费看视频 | 免费色片网站 | 日韩免费av一区 | 一级一毛片 | 精品久久久久国产 | 精品性久久 | 日本aa视频 | 寡妇高潮一级视频免费看 | 亚洲成人一二区 | 亚洲综合成人亚洲 | 91碰碰| 精品在线免费播放 | 偷拍网亚洲 | 狠狠狠狠干 | 极品美女av | 强行侵犯视频在线观看 | 三级成人在线 | 91久久视频 | 国产午夜精品久久久久久久久久 | 日本一区二区免费电影 | 国产精品久免费的黄网站 | 乱码一区二区三区 | 亚洲不卡中文字幕 | 福利视频第一页 | 国产调教一区 | 亚洲综合日韩精品欧美综合区 | 人人爱人人草 | 婷婷日 | 欧美久久久 | 国产高中女学生第一次 | 韩日精品在线 | 亚洲另类自拍 | 日韩动漫av | 国产极品999| 理论视频在线观看 | 影音先锋在线看片资源 | 少妇一级淫免费放 | 激情视频网站在线观看 | 国产精品白浆一区二小说 | 91成人看 | 野花av| 亚洲操操操| 日本免费黄网站 | sm在线看| 久色视频在线播放 | 香蕉成人av |