日韩性视频-久久久蜜桃-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...的全部內容,希望文章能夠幫你解決所遇到的問題。

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

主站蜘蛛池模板: 欧美视频一区二区三区在线观看 | 精品久久久久久无码国产 | 欧美成a | 99视频在线免费观看 | av影视网| 六月丁香激情综合 | 亚洲一级成人 | 五月在线 | 久久久三级视频 | 亚洲av无码一区二区三区在线观看 | 中文字幕+乱码+中文字幕一区 | 成人av综合网 | 天天干夜夜欢 | 亚洲av最新在线网址 | 五月激情综合婷婷 | 国产成人主播 | 亚洲自偷自偷偷色无码中文 | 51人人看| 91九色在线视频 | 神马午夜伦理影院 | 亚洲永久免费视频 | 免费精品| 美女主播福利视频 | 四虎影视www在线播放 | 三级自拍视频 | 黄色一级片. | 中文在线不卡 | 亚洲成a | 亚洲欧美综合在线观看 | 蜜桃视频免费网站 | 黄色链接视频 | 日韩全黄 | 中文字幕人妻一区二区在线视频 | 激情在线观看视频 | 久久久久久黄色片 | www.久久久| 中文字幕av不卡 | 国产毛片一区二区三区va在线 | 娇妻被肉到高潮流白浆 | 午夜一区二区三区 | 日韩精品小视频 | av免播放器 | 日本少妇喷水 | 国产欧美视频在线播放 | 手机在线永久免费观看av片 | 国产精品老熟女视频一区二区 | 亚洲人一区二区三区 | 美女扒开屁股让男人捅 | 色七七桃花综合影院 | 黄网站免费在线 | 国产在线精 | 性欧美8khd高清极品 | 日本高清黄色电影 | 野花视频在线免费观看 | 国产调教在线 | 日本变态折磨凌虐bdsm在线 | 秘密基地电影免费版观看国语 | 欧美国产一区二区 | 国产精品伊人 | 国产欧美日韩一区二区三区 | 小草av在线 | 一级作爱视频 | 亚洲美女影院 | 黄色片小视频 | 欧美理论在线 | 亚洲成人v | 亚洲小视频在线观看 | 久久一区av | 波多野结衣a v在线 欧洲免费av | 久久精品国产清自在天天线 | аⅴ天堂中文在线网 | av官网在线 | 免费黄在线看 | 欧美视频www | 欧美精品一区二区视频 | 亚洲av成人精品毛片 | 亚洲AV无码成人精品一区 | 香港三级网站 | 办公室荡乳欲伦交换bd电影 | 久久e热| 爱爱激情网| 午夜在线你懂的 | 日韩免费福利视频 | 久久av综合网 | 亚洲一区二区三区麻豆 | 国产人妖网站 | 成人免费视频国产在线观看 | 国产成人午夜精品无码区久久 | 亚洲国产情侣 | 男人的天堂日韩 | 日本男女啪啪 | 91在线精品李宗瑞 | 欧美日韩视频一区二区三区 | 农村少妇 | 97蜜桃网| 男男一级淫片免费播放 | 十八禁一区二区三区 | 欧美日韩在线观看视频 | 亚洲黑丝在线 |