欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解Java中異步轉(zhuǎn)同步的六種方法

 更新時間:2022年06月14日 15:04:29   作者:你呀不牛  
針對應(yīng)用中異步調(diào)用,能不能像同步調(diào)用一樣立刻獲取到命令的執(zhí)行結(jié)果,如何實現(xiàn)異步轉(zhuǎn)同步?不要擔心,本文就來為大家詳細講講Java中異步轉(zhuǎn)同步的六種方法,感興趣的可以了解一下

一、問題

應(yīng)用場景

應(yīng)用中通過框架發(fā)送異步命令時,不能立刻返回命令的執(zhí)行結(jié)果,而是異步返回命令的執(zhí)行結(jié)果。

那么,問題來了,針對應(yīng)用中這種異步調(diào)用,能不能像同步調(diào)用一樣立刻獲取到命令的執(zhí)行結(jié)果,如何實現(xiàn)異步轉(zhuǎn)同步?

二、分析

首先,解釋下同步和異步

  • 同步,就是發(fā)出一個調(diào)用時,在沒有得到結(jié)果之前,該調(diào)用就不返回或繼續(xù)執(zhí)行后續(xù)操作。
  • 異步,當一個異步過程調(diào)用發(fā)出后,調(diào)用者在沒有得到結(jié)果之前,就可以繼續(xù)執(zhí)行后續(xù)操作。當這個調(diào)用完成后,一般通過狀態(tài)、通知和回調(diào)來通知調(diào)用者。

對于異步調(diào)用,調(diào)用的返回并不受調(diào)用者控制。

異步轉(zhuǎn)同步主要實現(xiàn)思路:所有實現(xiàn)原理類似,是在發(fā)出調(diào)用的線程中進行阻塞等待結(jié)果,調(diào)用完成后通過回調(diào)、設(shè)置共享狀態(tài)或通知進行阻塞狀態(tài)的解除,繼續(xù)執(zhí)行后續(xù)操作。

三、實現(xiàn)方法

通常,實現(xiàn)中,不會無限的等待,一般會設(shè)定一個超時時間,具體超時時間根據(jù)具體場景確定。

下面以回調(diào)的方式介紹幾種常用實現(xiàn)異步轉(zhuǎn)同步的方法:

1.輪詢與休眠重試機制

采用輪詢與休眠重試機制,線程將反復(fù)在休眠和測試狀態(tài)條件中之間切換,直到超時或者狀態(tài)條件滿足繼續(xù)向下執(zhí)行。這種方式,超時時間控制不準確,sleep時間需要在響應(yīng)性和CPU使用率之間進行權(quán)衡。

private static long MILLIS_OF_WAIT_TIME = 300000L;// 等待時間 5分鐘
private final Object lock = new Object();

//3.結(jié)果返回后進行回調(diào),解除阻塞
@Override
public void callback(AsynResponse response){
    synchronized(lock){
        //設(shè)置狀態(tài)條件
}
 
public Result getResult() throws ErrorCodeException {
// 1.異步調(diào)用
 
// 2.阻塞等待異步響應(yīng)
    long future = System.currentTimeMillis() + MILLIS_OF_WAIT_TIME;
    long remaining = MILLIS_OF_WAIT_TIME;//剩余等待時間
    while(remaining > 0){
        synchronized(lock){
            if(狀態(tài)條件未滿足){
                remaining = future - System.currentTimeMillis();
                Thread.sleep(時間具體場景確定);
            }
        }  
````}
 
//4.超時或結(jié)果正確返回,對結(jié)果進行處理
     
    return result;
}

2.wait/notify

任意一個Java對象,都擁有一組監(jiān)視器方法(wait、notify、notifyAll等方法),這些方法和synchronized同步關(guān)鍵字配合,可以實現(xiàn)等待/通知模式。但是使用wait/notify,使線程的阻塞/喚醒對線程本身來說是被動的,要準確的控制哪個線程是很困難的,所以是要么隨機喚醒等待在條件隊列上一個線程(notify),要么喚醒所有的(notifyAll,但是很低效)。當多個線程基于不同條件在同一條件隊列上等待時,如果使用notify而不是notifyAll,很容易導(dǎo)致信號丟失的問題,所以必須謹慎使用wait/notify方法。

private static long MILLIS_OF_WAIT_TIME = 300000L;// 等待時間 5分鐘
private final Object lock = new Object();

//3.結(jié)果返回后進行回調(diào),解除阻塞
@Override
public void callback(AsynResponse response){
    synchronized(lock){
        lock.notifyAll();
}
 
public Result getResult() throws ErrorCodeException {
	// 1.異步調(diào)用
 
	// 2.阻塞等待異步響應(yīng)
    long future = System.currentTimeMillis() + MILLIS_OF_WAIT_TIME;
    long remaining = MILLIS_OF_WAIT_TIME;//剩余等待時間
    synchronized(lock){
        while(條件未滿足  && remaining > 0){ //被通知后要檢查條件
            lock.wait(remaining);
            remaining = future - System.currentTimeMillis();
        }  
````}
    
	//4.超時或結(jié)果正確返回,對結(jié)果進行處理
    return result;
}

3.Lock Condition

使用Lock的Condition隊列的實現(xiàn)方式和wait/notify方式類似,但是Lock支持多個Condition隊列,并且支持等待狀態(tài)中響應(yīng)中斷。

private static long SECONDS_OF_WAIT_TIME = 300L;// 等待時間 5分鐘
private final Lock lock = new ReentrantLock();
private final Condition condition = lock.newCondition();

//3.結(jié)果返回后進行回調(diào),解除阻塞
@Override
public void callback(AsynResponse response){
    lock.lock();//這是前提
    try {
        condition.signal();
    }finally {
        lock.unlock();
    }
}

public Result getResult() throws ErrorCodeException {
	// 1.異步調(diào)用
	// 2.阻塞等待異步響應(yīng)
    lock.lock();//這是前提
    try {
        condition.await();
    } catch (InterruptedException e) {
        //TODO
    }finally {
        lock.unlock();
    }
	//4.超時或結(jié)果正確返回,對結(jié)果進行處理
    return result;
}

4.CountDownLatch

使用CountDownLatch可以實現(xiàn)異步轉(zhuǎn)同步,它好比計數(shù)器,在創(chuàng)建實例CountDownLatch對象的時候傳入數(shù)字,每使用一次 countDown() 方法計數(shù)減1,當數(shù)字減到0時, await()方法后的代碼將可以執(zhí)行,未到0之前將一直阻塞等待。

private static long SECONDS_OF_WAIT_TIME = 300L;// 等待時間 5分鐘
private final CountDownLatch countDownLatch = new CountDownLatch(1);

//3.結(jié)果返回后進行回調(diào),解除阻塞
@Override
public void callback(AsynResponse response){
    countDownLatch.countDown();
}

public Result getResult() throws ErrorCodeException {
    // 1.異步調(diào)用

    // 2.阻塞等待異步響應(yīng)
    try {
        countDownLatch.await(SECONDS_OF_WAIT_TIME, TimeUnit.SECONDS);
    } catch (InterruptedException e) {
        //TODO
    }
	//4.超時或結(jié)果正確返回,對結(jié)果進行處理
    return result;
}

5.CyclicBarrier

讓一組線程達到一個屏障(也可以叫同步點)時被阻塞,直到等待最后一個線程到達屏障時,屏障才開門,所有被屏障攔截的線程才會繼續(xù)執(zhí)行。

每個線程通過調(diào)用await方法告訴CyclicBarrier我已經(jīng)到達了屏障,然后當前的的線程被阻塞。

private static long SECONDS_OF_WAIT_TIME = 300L;// 等待時間 5分鐘
private final CountDownLatch cyclicBarrier= new CyclicBarrier(2);//設(shè)置屏障攔截的線程數(shù)為2

//3.結(jié)果返回后進行回調(diào),解除阻塞
@Override
public void callback(AsynResponse response){
    //我也到達屏障了,可以開門了
    cyclicBarrier.await();
}

public Result getResult() throws ErrorCodeException {
    // 1.異步調(diào)用
    // 2.阻塞等待異步響應(yīng)
    try {
        //我到達屏障了,還沒開門,要等一等
        cyclicBarrier.await(SECONDS_OF_WAIT_TIME, TimeUnit.SECONDS);
    } catch (InterruptedException e) {
        //TODO
    }
	//4.超時或結(jié)果正確返回,對結(jié)果進行處理
    return result;
}

CountDownLatch和CyclicBarrier實現(xiàn)類似,區(qū)別是CountDownLatch的計數(shù)器只能使用一次,而CyclicBarrier的計數(shù)器可以使用reset重置,

所以CyclicBarrier能處理更為復(fù)雜的業(yè)務(wù)場景。在異步轉(zhuǎn)同步中,計數(shù)器不會重用,所以使用CountDownLatch實現(xiàn)更適合。

6.LockSupport

LockSupport定義了一組公共靜態(tài)方法,提供了最基本的線程阻塞和喚醒的方法。

private static long NANOS_OF_WAIT_TIME = 300000000L;// 等待時間 5分鐘
private final LockSupport lockSupport = new LockSupport();

//3.結(jié)果返回后進行回調(diào),解除阻塞
@Override
public void callback(AsynResponse response){
    lockSupport.unpark();
}

public Result getResult() throws ErrorCodeException {
    // 1.異步調(diào)用

    // 2.阻塞等待異步響應(yīng)
    try {
        lockSupport.parkNanos(NANOS_OF_WAIT_TIME);
    } catch (InterruptedException e) {
        //TODO
    }
	//4.超時或結(jié)果正確返回,對結(jié)果進行處理
    return result;

}

到此這篇關(guān)于詳解Java中異步轉(zhuǎn)同步的六種方法的文章就介紹到這了,更多相關(guān)Java異步轉(zhuǎn)同步內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 關(guān)于MD5算法原理與常用實現(xiàn)方式

    關(guān)于MD5算法原理與常用實現(xiàn)方式

    這篇文章主要介紹了關(guān)于MD5算法原理與常用實現(xiàn)方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-08-08
  • Springboot中攔截GET請求獲取請求參數(shù)驗證合法性核心方法

    Springboot中攔截GET請求獲取請求參數(shù)驗證合法性核心方法

    這篇文章主要介紹了Springboot中攔截GET請求獲取請求參數(shù)驗證合法性,在Springboot中創(chuàng)建攔截器攔截所有GET類型請求,獲取請求參數(shù)驗證內(nèi)容合法性防止SQL注入,這種方法適用攔截get類型請求,需要的朋友可以參考下
    2023-08-08
  • Java對象布局(JOL)實現(xiàn)過程解析

    Java對象布局(JOL)實現(xiàn)過程解析

    這篇文章主要介紹了Java對象布局(JOL)實現(xiàn)過程解析,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-04-04
  • Java中關(guān)于線程安全的三種解決方式

    Java中關(guān)于線程安全的三種解決方式

    這篇文章主要介紹了Java中關(guān)于線程安全的三種解決方式,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-09-09
  • springboot優(yōu)雅獲取前端參數(shù)的方法詳解

    springboot優(yōu)雅獲取前端參數(shù)的方法詳解

    現(xiàn)在的項目基本上都是前后端分離的項目,如何打通前后端,接收前端傳過來的參數(shù)呢,這篇文章小編就來和大家詳細介紹一下springboot如何優(yōu)雅的獲取前端參數(shù)吧
    2024-03-03
  • logback的addtivity屬性定義源碼解讀

    logback的addtivity屬性定義源碼解讀

    這篇文章主要為大家介紹了logback的addtivity屬性定義源碼解讀,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-11-11
  • 沒有編輯器的環(huán)境下是如何創(chuàng)建Servlet(Tomcat+Java)項目的?

    沒有編輯器的環(huán)境下是如何創(chuàng)建Servlet(Tomcat+Java)項目的?

    今天給大家?guī)淼氖顷P(guān)于Java的相關(guān)知識,文章圍繞著在沒有編輯器的環(huán)境下如何創(chuàng)建Servlet(Tomcat+Java)項目展開,文中有非常詳細的介紹及代碼示例,需要的朋友可以參考下
    2021-06-06
  • SpringBoot統(tǒng)計接口調(diào)用耗時的三種方式

    SpringBoot統(tǒng)計接口調(diào)用耗時的三種方式

    在實際開發(fā)中,了解項目中接口的響應(yīng)時間是必不可少的事情,SpringBoot 項目支持監(jiān)聽接口的功能也不止一個,接下來我們分別以 AOP、ApplicationListener、Tomcat 三個方面去實現(xiàn)三種不同的監(jiān)聽接口響應(yīng)時間的操作,需要的朋友可以參考下
    2024-06-06
  • 詳解Spring容器的使用流程

    詳解Spring容器的使用流程

    今天給大家?guī)淼氖顷P(guān)于Java的相關(guān)知識,文章圍繞著Spring容器的使用流程展開,文中有非常詳細的介紹及代碼示例,需要的朋友可以參考下
    2021-06-06
  • 基于java使用釘釘機器人向釘釘群推送消息

    基于java使用釘釘機器人向釘釘群推送消息

    這篇文章主要介紹了基于java使用釘釘機器人向釘釘群推送消息,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-11-11

最新評論