日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
SpringBoot并發(fā)編程學(xué)習(xí)歷程,你所需要的所有知識(shí)點(diǎn)!

本教程大概目錄:

創(chuàng)新互聯(lián)公司服務(wù)項(xiàng)目包括吳中網(wǎng)站建設(shè)、吳中網(wǎng)站制作、吳中網(wǎng)頁(yè)制作以及吳中網(wǎng)絡(luò)營(yíng)銷策劃等。多年來(lái),我們專注于互聯(lián)網(wǎng)行業(yè),利用自身積累的技術(shù)優(yōu)勢(shì)、行業(yè)經(jīng)驗(yàn)、深度合作伙伴關(guān)系等,向廣大中小型企業(yè)、政府機(jī)構(gòu)等提供互聯(lián)網(wǎng)行業(yè)的解決方案,吳中網(wǎng)站推廣取得了明顯的社會(huì)效益與經(jīng)濟(jì)效益。目前,我們服務(wù)的客戶以成都為中心已經(jīng)輻射到吳中省份的部分城市,未來(lái)相信會(huì)繼續(xù)擴(kuò)大服務(wù)區(qū)域并繼續(xù)獲得客戶的支持與信任!

  • 模擬單線程情節(jié)
  • 用Callable實(shí)現(xiàn) 并發(fā)編程
  • 用DeferedResult實(shí)現(xiàn)異步處理

###模擬單線程情節(jié)。

/**
 * Created by Fant.J.
 */
@RestController
@Slf4j
public class AsyncController {

    /**
     * 單線程測(cè)試
     * @return
     * @throws InterruptedException
     */
    @RequestMapping("/order")
    public String order() throws InterruptedException {
        log.info("主線程開(kāi)始");
        Thread.sleep(1000);
        log.info("主線程返回");
        return "success";
    }
}

我們把線程休息一秒當(dāng)作模擬處理業(yè)務(wù)所花費(fèi)的時(shí)間。很明顯能看出來(lái),這是個(gè)單線程。

nio-8080-exec-1表示主線程的線程1。

用Callable實(shí)現(xiàn) 并發(fā)編程

/**
     * 用Callable實(shí)現(xiàn)異步
     * @return
     * @throws InterruptedException
     */
    @RequestMapping("/orderAsync")
    public Callable orderAsync() throws InterruptedException {
        log.info("主線程開(kāi)始");
        Callable result = new Callable() {
            @Override
            public Object call() throws Exception {
                log.info("副線程開(kāi)始");
                Thread.sleep(1000);
                log.info("副線程返回");
                return "success";
            }
        };
        log.info("主線程返回");
        return result;
    }

我們可以看到,主線程的開(kāi)始和返回(結(jié)束處理)是首先執(zhí)行的,然后副線程才執(zhí)行真正的業(yè)務(wù)處理。說(shuō)明主線程在這里的作用是調(diào)用(喚醒)子線程,子線程處理完會(huì)返回一個(gè)Object對(duì)象,然后返回給用戶。

這樣雖然實(shí)現(xiàn)了并發(fā)處理,但是有一個(gè)問(wèn)題,就是主線程和副線程沒(méi)有做到完全分離,畢竟是一個(gè)嵌套進(jìn)去的副線程。

所以為了優(yōu)化我們的實(shí)現(xiàn),我在這里模擬 消息中間件 來(lái)實(shí)現(xiàn)主線程副線程的完全分離。

用DeferedResult實(shí)現(xiàn)異步處理

因?yàn)楸菊轮饕v的是并發(fā)編程原理,所以這里我們不用現(xiàn)成的消息隊(duì)列來(lái)搞,我們模擬一個(gè)消息隊(duì)列來(lái)處理。

MockQueue .java

/**
 * 模擬消息隊(duì)列 類
 * Created by Fant.J.
 */
@Component
@Slf4j
public class MockQueue {

    //下單消息
    private String placeOrder;
    //訂單完成消息
    private String completeOrder;

    public String getPlaceOrder() {
        return placeOrder;
    }

    public void setPlaceOrder(String placeOrder) throws InterruptedException {
        new Thread(()->{
            log.info("接到下單請(qǐng)求"+placeOrder);
            //模擬處理
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //給completeOrder賦值
            this.completeOrder = placeOrder;
            log.info("下單請(qǐng)求處理完畢"+placeOrder);
        }).start();
    }

    public String getCompleteOrder() {
        return completeOrder;
    }

    public void setCompleteOrder(String completeOrder) {
        this.completeOrder = completeOrder;
    }
}

注意再setPlaceOrder(String placeOrder)方法里,我創(chuàng)建了一個(gè)新的線程來(lái)處理接單的操作(為什么要建立新線程,怕主線程在這掛起,此段邏輯也沒(méi)有線程安全問(wèn)題,況且異步處理更快)。傳進(jìn)來(lái)的參數(shù)是個(gè) 訂單號(hào) ,經(jīng)過(guò)1s的處理成功后,把訂單號(hào)傳給completeOrder 字段,說(shuō)明用戶下單成功,我在下面付controller調(diào)用該方法的代碼。

//注入模擬消息隊(duì)列類
    @Autowired
    private MockQueue mockQueue;
    @Autowired
    private DeferredResultHolder deferredResultHolder;
    ....
    @RequestMapping("/orderMockQueue")
    public DeferredResult orderQueue() throws InterruptedException {
        log.info("主線程開(kāi)始");

        //隨機(jī)生成8位數(shù)
        String orderNumber = RandomStringUtils.randomNumeric(8);
        mockQueue.setPlaceOrder(orderNumber);

        DeferredResult result = new DeferredResult();
        deferredResultHolder.getMap().put(orderNumber,result);
        Thread.sleep(1000);
        log.info("主線程返回");

        return result;
    }

好了,然后我們還需要一個(gè)中介類來(lái)存放訂單號(hào)和處理結(jié)果。為什么需要這么一個(gè)類呢,因?yàn)槲覀冎罢f(shuō)過(guò)要實(shí)現(xiàn)主線程和副線程分離,所以需要一個(gè)中介來(lái)存放處理信息(比如:這個(gè)訂單號(hào)信息,和處理結(jié)果信息),我們判斷處理結(jié)果是否為空就知道該副線程執(zhí)行了沒(méi)有。所以我們寫(xiě)一個(gè)中介類DeferredResultHolder 。

######DeferredResultHolder .java:

/**
 *  訂單處理情況 中介/持有者
 * Created by Fant.J.
 */
@Component
public class DeferredResultHolder {

    /**
     * String: 訂單號(hào)
     * DeferredResult:處理結(jié)果
     */
    private Map map = new HashMap<>();

    public Map getMap() {
        return map;
    }

    public void setMap(Map map) {
        this.map = map;
    }
}

在重復(fù)一次-.-,為什么需要這么一個(gè)類呢,因?yàn)槲覀冎罢f(shuō)過(guò)要實(shí)現(xiàn)主線程和副線程分離,所以需要一個(gè)中介來(lái)存放處理信息(比如:這個(gè)訂單號(hào)信息,和處理結(jié)果信息),一個(gè)訂單肯定要對(duì)應(yīng)一個(gè)結(jié)果。不然豈不是亂了套。

DeferredResult是用來(lái)放處理結(jié)果的對(duì)象。

好了,那新問(wèn)題又來(lái)了,我們?cè)趺慈ヅ袛嘤唵翁幚沓晒α藳](méi)有,我們此時(shí)就需要寫(xiě)一個(gè)監(jiān)聽(tīng)器,過(guò)100毫秒監(jiān)聽(tīng)一次MockQueue類中的completeOrder中是否有值,如果有值,那么這個(gè)訂單就需要被處理。我們寫(xiě)一個(gè)監(jiān)聽(tīng)器。

######QueueListener .java:

/**
 * Queue監(jiān)聽(tīng)器
 * Created by Fant.J.
 */
@Component
@Slf4j
public class QueueListener implements ApplicationListener{

    @Autowired
    private MockQueue mockQueue;

    @Autowired
    private DeferredResultHolder deferredResultHolder;


    @Override
    public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {

        new Thread(()->{
            while(true){
                //判斷CompleteOrder字段是否是空
                if (StringUtils.isNotBlank(mockQueue.getCompleteOrder())){

                    String orderNumber = mockQueue.getCompleteOrder();

                    deferredResultHolder.getMap().get(orderNumber).setResult("place order success");

                    log.info("返回訂單處理結(jié)果");

                    //將CompleteOrder設(shè)為空,表示處理成功
                    mockQueue.setCompleteOrder(null);
                }else {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
    }
}

我們可以看到一共有三個(gè)不同的線程來(lái)處理。

分割線后,我再給大家?guī)?lái)一批干貨,自定義線程池https://www.jianshu.com/p/832f2b162450。

學(xué)完這個(gè)后,再看下面的。

我們前面的代碼中,有兩部分有用new Thread()來(lái)創(chuàng)建線程,我們有自己的線程池后,就可以用線程池來(lái)分配線程任務(wù)了,我在自定義線程里有講,我用的是第二種配置方法(用@Async注解來(lái)給線程 )。
修改如下:

@Async
    public void setPlaceOrder(String placeOrder) throws InterruptedException {
            log.info("接到下單請(qǐng)求"+placeOrder);
            //模擬處理
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //給completeOrder賦值
            this.completeOrder = placeOrder;
            log.info("下單請(qǐng)求處理完畢"+placeOrder);
    }

我們看看效果:

圈紅圈的就是我們自己定義的線程池里分配的線程。


當(dāng)前題目:SpringBoot并發(fā)編程學(xué)習(xí)歷程,你所需要的所有知識(shí)點(diǎn)!
網(wǎng)頁(yè)地址:http://www.5511xx.com/article/ccdijgg.html