高階多線程設(shè)計模式:Future,不看你會后悔

說到多線程的future,百度 多線程 future,網(wǎng)上也有各式各樣的例子,寫的比我還要好,但是實在是這個模式或者說例子以及實用性太大了,我不得不拿出來講,甚至在實際生產(chǎn)環(huán)境中也是可以用的.我呢,也是拿出網(wǎng)上的例子詳細(xì)的講一遍~~

看下面的圖↓↓↓↓↓

傳統(tǒng)下單流程.jpg

如上圖,傳統(tǒng)的訂單下單流程,首先減商品庫存,然后生成訂單,然后生成訂單詳情,再通知短信等等,全部邏輯程序都是串行執(zhí)行的.假如我們的系統(tǒng)特別'困難',減商品庫存要1秒,生成訂單要1秒,生成詳情也要1秒,發(fā)送短信有可能要5秒,這里還不算查詢商品的庫存夠不夠下單等等,那么一系列的操作就要花很多時間.

那么引入多線程的future有什么好處呢?看下圖↓↓↓↓↓↓↓

多線程future下單流程.jpg

看這圖很簡單,用戶下單,future對象直接告訴你下單成功,返回給你一個假數(shù)據(jù),同時自己偷偷的新建了一個或者幾個線程處理其他業(yè)務(wù)邏輯,等邏輯處理完了,再返回一個正確的結(jié)果.

然后是上代碼~~

public interface Data {
    String getRequest();
}
public class RealData implements Data {
    private String result;

    public RealData(String request) {
        System.out.println("根據(jù)" + request + "進行查詢..,要花很久時間");
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("操作完畢,獲取結(jié)果");
        result = "查詢結(jié)果";
    }

    public String getRequest() {
        return result;
    }
}
public class FutureData implements Data {

    private RealData realData;

    private boolean isReady = false;

    public synchronized String getRequest() {

        while (!isReady) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        return this.realData.getRequest();
    }

    public synchronized void setRealData(RealData realData) {
        if (isReady) {
            return;
        }
        this.realData = realData;
        isReady = true;
        notify();
    }
}

public class FutureClient {
    public Data request(final String request) {
        final FutureData futureData = new FutureData();

        new Thread(new Runnable() {

            public void run() {
                RealData realData = new RealData(request);
                futureData.setRealData(realData);
            }
        }).start();

        return futureData;
    }
}
public class Main {

    public static void main(String[] args) {
        FutureClient fClient = new FutureClient();
        
        Data data = fClient.request("hello,world");
        
        System.out.println("請求發(fā)送成功...");
        System.out.println("干其他的事情...");

        String result = data.getRequest();

        System.out.println(result);
    }
}

一共5個類,剛開始看會有點懵逼,正常,我也是懵逼的,我到現(xiàn)在也還是懂了90%,為什么懂90%就敢講,其實也差不多了~自己按照代碼一個單詞一個單詞的教,自然就懂思想.就按照我貼的代碼順序我們一點一點看,這個模式很有意思的,真的能學(xué)到很多東西.

首先看這個接口Data,只有一個方法getRequest(),返回String字符串.

然后再看RealData這個類,實現(xiàn)了Data接口,首先他有構(gòu)造函數(shù),打印了兩句話,然后中間sleep一下,做這個sleep我們可以想象成在處理業(yè)務(wù)邏輯.

接著再看FutureData這個類,也實現(xiàn)了Data接口.先看FutureData的getRequest()方法,這個方法先死循環(huán)判斷boolean,如果isReady是true,就阻塞著,不然就返回RealData真的getRequest()方法(真實的結(jié)果).然后再看setRealData(),判斷isReady,如果是ture,直接return,如果不是就賦值RealData,并修改isReady,然后notify()..

其實很好理解,不要看到synchronized,notify,wait就暈了,FutureData這個類干了啥,你想,wait什么?不就是等notify嗎,如果沒有notify,那我就得等著,等什么?還是等通知啊,只有通知了,那么我才能進行下去,進行下去什么?--->RealData.getRequset()啊,就是真實的數(shù)據(jù),為什么要等?因為還在處理啊,只有真實的數(shù)據(jù)處理完了,然后通知,也就是說FutureData這個類的setRealData()只是起到通知的作用,再看setRealData()傳入的是RealData對象,RealData干了啥事,不就是有個構(gòu)造函數(shù)實現(xiàn)自己的業(yè)務(wù)嗎,實現(xiàn)完了就可以通知!!還不懂,自己敲代碼..結(jié)合我說的多讀幾遍,別被饒暈了~~~

最后看FutureClient 這個類,最簡單了,返回futureData,偷偷開了線程,看到RealData realData = new RealData(request)沒有?就是開始執(zhí)行業(yè)務(wù)了,然后當(dāng)FutureData這個類的setRealData(RealData realData)時就通知了..我現(xiàn)在都100%懂了~~~~~~~

最后Main方法就不說了~

打印結(jié)果↓↓↓↓↓↓

請求發(fā)送成功...
干其他的事情...
根據(jù)hello,world進行查詢..,要花很久時間
操作完畢,獲取結(jié)果
查詢結(jié)果

第四句話和第五話是2秒后才出來的~~~~

上面的原理你可以不用懂,當(dāng)然懂最好了,可以在面試官面前吹牛逼啊..future模式這么兇殘,jdk也有實現(xiàn)的,在java.util.concurrent,又是concurrent,這個工具類真的是強大上代碼,就不說了~

import java.util.concurrent.Callable;

public class RealData implements Callable<String> {
    private String Data;

    public RealData(String Data) {
        this.Data = Data;
    }

    public String call() throws Exception {
        //利用sleep來表示任務(wù)處理
        Thread.sleep(2000);

        return "這是處理"+Data+"結(jié)果";
    }
}
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;

public class Main {

    public static void main(String[] args) throws Exception {
        Long start = System.currentTimeMillis();

        FutureTask<String> futureTask = new FutureTask<>(new RealData("hello,world"));
        ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(1);
        newFixedThreadPool.submit(futureTask);

        // 表示正在處理其他邏輯,或者業(yè)務(wù)
        Thread.sleep(1000);

        System.out.println("最后結(jié)果-->" + futureTask.get());

        Long end = System.currentTimeMillis();

        Long useTime = end - start;

        System.out.println("程序運行了-->" + useTime + "毫秒");
    }

}

最后奉上打印結(jié)果↓↓↓↓↓

最后結(jié)果-->這是處理hello,world結(jié)果
程序運行了-->2004毫秒

看2秒就執(zhí)行完了..最好自己敲一遍~~~~~

有啥不懂的請加qq727865942,微信號 cto_zej,覺得是干貨請打賞~~~~~~~~~~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 接著上節(jié) condition_varible ,本節(jié)主要介紹future的內(nèi)容,練習(xí)代碼地址。本文參考http:/...
    jorion閱讀 15,056評論 1 5
  • 寫在前面的話: 這篇博客是我從這里“轉(zhuǎn)載”的,為什么轉(zhuǎn)載兩個字加“”呢?因為這絕不是簡單的復(fù)制粘貼,我花了五六個小...
    SmartSean閱讀 4,956評論 12 45
  • 先看幾個概念:線程:進程中負(fù)責(zé)程序執(zhí)行的執(zhí)行單元。一個進程中至少有一個線程。多線程:解決多任務(wù)同時執(zhí)行的需求,合理...
    yeying12321閱讀 614評論 0 0
  • Java-Review-Note——4.多線程 標(biāo)簽: JavaStudy PS:本來是分開三篇的,后來想想還是整...
    coder_pig閱讀 1,772評論 2 17
  • 這道題考查寫shellcode, 用keystone折騰了半天上網(wǎng)一查發(fā)現(xiàn)我們對pwntools的運用真的不夠熟練...
    hyrathon閱讀 669評論 0 0

友情鏈接更多精彩內(nèi)容