想參加多人運動?並行流(ParallelStream)模式教你成為時間管理大師

current_person發表於2020-10-10

目的

提高程式執行效率, 減少響應時間或者增加吞吐量

例子程式碼

最近羅*祥, 福報廠P12 jf 引起了大家的關注, 二位都是因為私人生活問題, 搞的微博程式設計師天天加班加伺服器, 讓我等吃了一個又一個瓜, 真是犯了全天下男人都會犯的錯, 我感覺我就不會犯這種錯, 當然是因為我是個好男人主要是因為沒錢, 沒名, 身體也…

行了行了, 說遠了, 我們還是可以從他們身上學習到這個時間管理大法的, 從而可以有時間多參加 ‘多人運動’

我們假設有這麼一個 ‘太虛公子’ 這個一個壞男孩, 要和三位女孩一起玩(shui)耍(jiao)

壞男孩類:

@Data
@AllArgsConstructor
public class BadBoy {

    private String name;

    public void playWithGirls(List<Girl> girls) {
        for (Girl girl : girls) {
            girl.playWithBody(this);
        }
    }
}

女孩類:

@Data
@AllArgsConstructor
public class Girl {

    private String name;

    @SneakyThrows
    void playWithBody(BadBoy badBoy) {
        System.out.println(name + "開始和" + badBoy.getName() + "玩");
        doSomethingMySelf();
        System.out.println(name + "玩完了");
    }

    private void doSomethingMySelf() throws InterruptedException {
        //'睡覺' 1 秒完事
        Thread.sleep(500);
        System.out.println(name + "自己吃飯, 化妝, 發微博");
        Thread.sleep(500);

    }
}

我們讓 ‘太虛公子’ 與三位女孩玩耍:

StopWatch stopwatch = StopWatch.createStarted();
BadBoy lzx = new BadBoy("空虛公子");
lzx.playWithGirls(List.of(new Girl("周*青"), new Girl("花花董花花"), new Girl("張大*")));
stopwatch.stop();
System.out.println("total time: " + stopwatch.getTime(TimeUnit.SECONDS));

我們看下輸出和總耗時:

*青開始和 空虛公子玩
周*青自己吃飯, 化妝, 發微博
周*青玩完了
花花董花花開始和 空虛公子玩
花花董花花自己吃飯, 化妝, 發微博
花花董花花玩完了
張大*開始和 空虛公子玩
張大*自己吃飯, 化妝, 發微博
張大*玩完了
total time: 3

問題分析

就是時間管理不太好, 三個女孩需要三秒, 那不是太慢了, 能不能三個女孩就花一秒多的時間就能行呢

並行流模式

我們定義一個時間管理大師壞男孩:

@Data
@AllArgsConstructor
public class ParallelBadBoy {

    private String name;

    public void playWithGirls(List<Girl> girls) {
        girls.parallelStream().forEach(girl -> girl.playWithBody(this));
    }
}

Girl 增加一個與時間管理大師玩的多型方法:

@Data
@AllArgsConstructor
public class Girl {

    private String name;

    @SneakyThrows
    void playWithBody(BadBoy badBoy) {
        System.out.println(name + "開始和" + badBoy.getName() + "玩");
        doSomethingMySelf();
        System.out.println(name + "玩完了");
    }

    @SneakyThrows
    void playWithBody(ParallelBadBoy badBoy) {
        System.out.println(name + "開始和" + badBoy.getName() + "玩");
        doSomethingMySelf();
        System.out.println(name + "玩完了");
    }

    private void doSomethingMySelf() throws InterruptedException {
        //'睡覺' 1 秒完事
        Thread.sleep(500);
        System.out.println(name + "自己吃飯, 化妝, 發微博");
        Thread.sleep(500);

    }
}

呼叫:

StopWatch stopwatch = StopWatch.createStarted();
ParallelBadBoy lzx = new ParallelBadBoy("八爪魚");
lzx.playWithGirls(List.of(new Girl("周*青"), new Girl("花花董花花"), new Girl("張大*")));
stopwatch.stop();
System.out.println("total time: " + stopwatch.getTime(TimeUnit.SECONDS));

輸出:

*青開始和八爪魚玩
花花董花花開始和八爪魚玩
張大*開始和八爪魚玩
花花董花花自己吃飯, 化妝, 發微博
張大*自己吃飯, 化妝, 發微博
周*青自己吃飯, 化妝, 發微博
花花董花花玩完了
張大*玩完了
周*青玩完了
total time: 1

更近非同步

如果不自定義執行緒池, 預設的是一個公有的執行緒池, 壞男孩太多了反而可能比序列還慢

@Data
@AllArgsConstructor
public class ParallelBadBoy {
    private static final ForkJoinPool COLUMN_POOL = new ForkJoinPool(30);

    private String name;

    public void playWithGirls(List<Girl> girls) {
        COLUMN_POOL.submit(() -> girls.parallelStream().forEach(girl -> girl.playWithBody(this)));
    }
}

課後作業

  1. 把 BadBoy 和 ParallelBadBody 抽象成一個類
  2. 思考並行流一定可以加快速度麼
  3. 瞭解普通執行緒池的技術和並行流執行緒池的區別, 比較二者的優劣, 我們有這麼一個貸款產品需要展示給使用者, 如果需要從多個系統取資料做聚合展示, 比如從 A 系統取期限, 還款方式和可貸額度, 從B 系統取優惠卷列表, C 系統取登入使用者資訊, 這種情況是否適合使用並行流方式

微信:
在這裡插入圖片描述

相關文章