最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java多線程間的5種通信方式小結(jié)

 更新時間:2023年10月13日 08:42:45   作者:終有救贖  
有兩個線程,A 線程向一個集合里面依次添加元素“abc”字符串,一共添加十次,當(dāng)添加到第五次的時候,希望 B 線程能夠收到 A 線程的通知,然后 B 線程執(zhí)行相關(guān)的業(yè)務(wù)操作,本文介紹的5種通信方式都是基本這兩種模型來實現(xiàn)的,需要的朋友可以參考下

問題

有兩個線程,A 線程向一個集合里面依次添加元素“abc”字符串,一共添加十次,當(dāng)添加到第五次的時候,希望 B 線程能夠收到 A 線程的通知,然后 B 線程執(zhí)行相關(guān)的業(yè)務(wù)操作。線程間通信的模型有兩種:共享內(nèi)存和消息傳遞,以下方式都是基本這兩種模型來實現(xiàn)的。

一、使用 volatile 關(guān)鍵字

基于 volatile 關(guān)鍵字來實現(xiàn)線程間相互通信是使用共享內(nèi)存的思想。大致意思就是多個線程同時監(jiān)聽一個變量,當(dāng)這個變量發(fā)生變化的時候 ,線程能夠感知并執(zhí)行相應(yīng)的業(yè)務(wù)。這也是最簡單的一種實現(xiàn)方式

public class TestSync {
    //定義共享變量來實現(xiàn)通信,它需要volatile修飾,否則線程不能及時感知
    static volatile boolean notice = false;
    public static void main(String[] args) {
        List<String>  list = new ArrayList<>();
        //線程A
        Thread threadA = new Thread(() -> {
            for (int i = 1; i <= 10; i++) {
                list.add("abc");
                System.out.println("線程A添加元素,此時list的size為:" + list.size());
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if (list.size() == 5)
                    notice = true;
            }
        });
        //線程B
        Thread threadB = new Thread(() -> {
            while (true) {
                if (notice) {
                    System.out.println("線程B收到通知,開始執(zhí)行自己的業(yè)務(wù)...");
                    break;
                }
            }
        });
        //需要先啟動線程B
        threadB.start();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 再啟動線程A
        threadA.start();
    }
}

二、使用 Object 類的 wait()/notify()

Object 類提供了線程間通信的方法:wait()、notify()notifyAll(),它們是多線程通信的基礎(chǔ),而這種實現(xiàn)方式的思想自然是線程間通信。

注意:wait/notify 必須配合 synchronized 使用,wait 方法釋放鎖,notify 方法不釋放鎖。wait 是指在一個已經(jīng)進(jìn)入了同步鎖的線程內(nèi),讓自己暫時讓出同步鎖,以便其他正在等待此鎖的線程可以得到同步鎖并運(yùn)行,只有其他線程調(diào)用了notify(),notify并不釋放鎖,只是告訴調(diào)用過wait()的線程可以去參與獲得鎖的競爭了,但不是馬上得到鎖,因為鎖還在別人手里,別人還沒釋放,調(diào)用 wait() 的一個或多個線程就會解除 wait 狀態(tài),重新參與競爭對象鎖,程序如果可以再次得到鎖,就可以繼續(xù)向下運(yùn)行。

public class TestSync {
    public static void main(String[] args) {
        //定義一個鎖對象
        Object lock = new Object();
        List<String>  list = new ArrayList<>();
        // 線程A
        Thread threadA = new Thread(() -> {
            synchronized (lock) {
                for (int i = 1; i <= 10; i++) {
                    list.add("abc");
                    System.out.println("線程A添加元素,此時list的size為:" + list.size());
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    if (list.size() == 5)
                        lock.notify();//喚醒B線程
                }
            }
        });
        //線程B
        Thread threadB = new Thread(() -> {
            while (true) {
                synchronized (lock) {
                    if (list.size() != 5) {
                        try {
                            lock.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.println("線程B收到通知,開始執(zhí)行自己的業(yè)務(wù)...");
                }
            }
        });
        //需要先啟動線程B
        threadB.start();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //再啟動線程A
        threadA.start();
    }
}

由輸出結(jié)果,在線程 A 發(fā)出 notify() 喚醒通知之后,依然是走完了自己線程的業(yè)務(wù)之后,線程 B 才開始執(zhí)行,正好說明 notify() 不釋放鎖,而 wait() 釋放鎖。

三、使用JUC工具類 CountDownLatch

jdk1.5 之后在java.util.concurrent包下提供了很多并發(fā)編程相關(guān)的工具類,簡化了并發(fā)編程代碼的書寫,CountDownLatch 基于 AQS 框架,相當(dāng)于也是維護(hù)了一個線程間共享變量 state。

public class TestSync {
    public static void main(String[] args) {
        CountDownLatch countDownLatch = new CountDownLatch(1);
        List<String>  list = new ArrayList<>();
        //線程A
        Thread threadA = new Thread(() -> {
            for (int i = 1; i <= 10; i++) {
                list.add("abc");
                System.out.println("線程A添加元素,此時list的size為:" + list.size());
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if (list.size() == 5)
                    countDownLatch.countDown();
            }
        });
        //線程B
        Thread threadB = new Thread(() -> {
            while (true) {
                if (list.size() != 5) {
                    try {
                        countDownLatch.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println("線程B收到通知,開始執(zhí)行自己的業(yè)務(wù)...");
                break;
            }
        });
        //需要先啟動線程B
        threadB.start();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //再啟動線程A
        threadA.start();
    }
}

四、使用 ReentrantLock 結(jié)合 Condition

public class TestSync {
    public static void main(String[] args) {
        ReentrantLock lock = new ReentrantLock();
        Condition condition = lock.newCondition();
        List<String> list = new ArrayList<>();
        //線程A
        Thread threadA = new Thread(() -> {
            lock.lock();
            for (int i = 1; i <= 10; i++) {
                list.add("abc");
                System.out.println("線程A添加元素,此時list的size為:" + list.size());
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if (list.size() == 5)
                    condition.signal();
            }
            lock.unlock();
        });
        //線程B
        Thread threadB = new Thread(() -> {
            lock.lock();
            if (list.size() != 5) {
                try {
                    condition.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("線程B收到通知,開始執(zhí)行自己的業(yè)務(wù)...");
            lock.unlock();
        });
        threadB.start();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        threadA.start();
    }
}

這種方式使用起來并不是很好,代碼編寫復(fù)雜,而且線程 B 在被 A 喚醒之后由于沒有獲取鎖還是不能立即執(zhí)行,也就是說,A 在喚醒操作之后,并不釋放鎖。這種方法跟 Object 的 wait()/notify() 一樣。

五、基本 LockSupport 實現(xiàn)線程間的阻塞和喚醒

LockSupport 是一種非常靈活的實現(xiàn)線程間阻塞和喚醒的工具,使用它不用關(guān)注是等待線程先進(jìn)行還是喚醒線程先運(yùn)行,但是得知道線程的名字。

public class TestSync {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        //線程B
        final Thread threadB = new Thread(() -> {
            if (list.size() != 5) {
                LockSupport.park();
            }
            System.out.println("線程B收到通知,開始執(zhí)行自己的業(yè)務(wù)...");
        });
        //線程A
        Thread threadA = new Thread(() -> {
            for (int i = 1; i <= 10; i++) {
                list.add("abc");
                System.out.println("線程A添加元素,此時list的size為:" + list.size());
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if (list.size() == 5)
                    LockSupport.unpark(threadB);
            }
        });
        threadA.start();
        threadB.start();
    }
}

以上就是Java多線程間的5種通信方式小結(jié)的詳細(xì)內(nèi)容,更多關(guān)于Java多線程間通信方式的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Java 和 JavaScript 真正通用的Base64編碼詳解

    Java 和 JavaScript 真正通用的Base64編碼詳解

    這篇文章主要介紹了Java 和 JavaScript 真正通用的Base64編碼詳解的相關(guān)資料,附有Java和Javascript 的Base64編碼,需要的朋友可以參考下
    2016-11-11
  • SpringSecurity配置HTTPS的實現(xiàn)

    SpringSecurity配置HTTPS的實現(xiàn)

    本文介紹了SpringBoot項目中配置HTTPS并集成SpringSecurity,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2025-01-01
  • 使用Lombok導(dǎo)致打印的tostring中缺少父類的屬性問題

    使用Lombok導(dǎo)致打印的tostring中缺少父類的屬性問題

    使用Lombok時,若發(fā)現(xiàn)@Data注解的@ToString不包含父類屬性,可通過添加@ToString(callSuper=true)解決,此方法確保在生成toString()時包括父類的屬性,有效解決只打印子類屬性的問題,這種做法對于需要完整信息展示的場景尤為重要
    2024-11-11
  • Google Guava 緩存工具使用詳解

    Google Guava 緩存工具使用詳解

    這篇文章主要介紹了Guava自加載緩存LoadingCache使用指南,通過這些內(nèi)容介紹,了解了LoadingCache的基本原理和用法,包括如何創(chuàng)建和配置緩存,以及如何結(jié)合Java?8的特性來優(yōu)化代碼,需要的朋友可以參考下
    2023-12-12
  • Java?日志中打印服務(wù)器?IP快速區(qū)分多服務(wù)器日志歸屬問題

    Java?日志中打印服務(wù)器?IP快速區(qū)分多服務(wù)器日志歸屬問題

    文章介紹了在分布式部署場景中如何通過Java代碼獲取服務(wù)器IPv4地址,并將IP嵌入日志中,以便快速定位日志所屬服務(wù)器,文中提供了兩種實現(xiàn)方案:手動拼接IP和使用MDC+日志框架配置,并詳細(xì)說明了每種方案的優(yōu)缺點(diǎn)和具體實現(xiàn)步驟,感興趣的朋友跟隨小編一起看看吧
    2026-02-02
  • Java實現(xiàn)堆排序(Heapsort)實例代碼

    Java實現(xiàn)堆排序(Heapsort)實例代碼

    這篇文章主要介紹了Java實現(xiàn)堆排序(Heapsort)實例代碼,有需要的朋友可以參考一下
    2013-12-12
  • Springboot項目編譯后未能加載靜態(tài)資源文件的問題

    Springboot項目編譯后未能加載靜態(tài)資源文件的問題

    這篇文章主要介紹了Springboot項目編譯后未能加載靜態(tài)資源文件的問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-08-08
  • 利用Java工具類Hutool實現(xiàn)驗證碼校驗功能

    利用Java工具類Hutool實現(xiàn)驗證碼校驗功能

    這篇文章主要介紹了利用Java工具類Hutool實現(xiàn)驗證碼校驗功能,利用Hutool實現(xiàn)驗證碼校驗,校驗的Servlet與今天的第一篇是一樣的,唯一就是驗證碼的生成是不一樣的,利用Hutool生成驗證碼更快捷.需要的朋友可以參考下
    2022-10-10
  • java枚舉類型-Enum

    java枚舉類型-Enum

    本文詳細(xì)介紹了 Java1.5 引入的新特性枚舉中的關(guān)鍵字enum,運(yùn)用大量的代碼加以解釋,相信可以幫助到正在學(xué)習(xí)該知識的小伙伴,大家可以參考一下
    2021-08-08
  • 詳解Java集合中的基本數(shù)據(jù)結(jié)構(gòu)

    詳解Java集合中的基本數(shù)據(jù)結(jié)構(gòu)

    總有小伙伴讓我總結(jié)一下Java集合中的基本數(shù)據(jù)結(jié)構(gòu)的相關(guān)知識,今天特地整理了本篇文章,文中有非常詳細(xì)的介紹,需要的朋友可以參考下
    2021-06-06

最新評論

黔南| 迁安市| 汝阳县| 康马县| 班玛县| 南丰县| 齐齐哈尔市| 铜山县| 花莲市| 阳高县| 潞西市| 宁城县| 香格里拉县| 内乡县| 临夏县| 吴桥县| 东丰县| 汾西县| 抚远县| 永定县| 闽侯县| 宣城市| 孟州市| 芒康县| 宁陕县| 昭觉县| 伊川县| 苗栗县| 治多县| 潮安县| 南宫市| 渝北区| 澳门| 吉水县| 祁阳县| 山东省| 嘉善县| 建湖县| 彝良县| 介休市| 确山县|