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

Java線程協(xié)作的兩種方式小結(jié)

 更新時間:2023年05月05日 10:27:32   作者:思維的深度  
Java中線程協(xié)作的最常見的兩種方式是利用Object.wait()、Object.notify()和使用Condition,本文主要介紹了Java線程協(xié)作的兩種方式小結(jié),文中通過示例代碼介紹的非常詳細,需要的朋友們下面隨著小編來一起學習學習吧

為什么線程之間需要協(xié)作

線程之間相互配合,完成某項工作,比如:一個線程修改了一個對象的值,而另一個線程感知到了變化,然后進行相應(yīng)的操作,整個過程開始于一個線程,而最終執(zhí)行又是另一個線程。前者是生產(chǎn)者,后者就是消費者,這種模式隔離了“做什么”(What)和“怎么做”(How)。簡單的辦法是讓消費者線程不斷地循環(huán)檢查變量是否符合預(yù)期,在while循環(huán)中設(shè)置不滿足的條件,如果條件滿足則退出while循環(huán),從而完成消費者的工作。這樣進行線程之間的協(xié)作卻存在如下2個問題:

(1)難以確保及時性。

(2)難以降低開銷。如果降低睡眠的時間,比如休眠1毫秒,這樣消費者能更加迅速地發(fā)現(xiàn)條件變化,但是卻可能消耗更多的處理器資源,造成了無端的浪費。

那么有沒有什么辦法可以解決以上2個問題呢?此時等待/通知機制毫不客氣的站出來說,都讓開,交給我,我能行! 

介紹

Java中線程協(xié)作的最常見的兩種方式:利用Object.wait()、Object.notify()和使用Condition

方法一

Object中的wait、notify、notifyAll方法定義如下

  • public final native void notify(); public final native void notifyAll(); public final native void wait(long timeout) throws InterruptedException;
  • wait()、notify()和notifyAll()方法是本地方法,并且為final方法,無法被重寫
  • 調(diào)用某個對象的wait()方法能讓當前線程阻塞,并且當前線程必須擁有此對象的monitor(即鎖)
  • 調(diào)用某個對象的notify()方法能夠喚醒一個正在等待這個對象的monitor的線程,如果有多個線程都在等待這個對象的monitor,則只能喚醒其中一個線程
  • 調(diào)用notifyAll()方法能夠喚醒所有正在等待這個對象的monitor的線程
  • 之所以這三個方法聲明在Object類中是因為每個對象都擁有monitor(即鎖)
  • 調(diào)用某個對象的wait()方法,當前線程必須擁有這個對象的monitor(即鎖),因此調(diào)用wait()方法必須在同步塊或者同步方法中進行

示例

public class Test {
    public static Object object = new Object();
    public static void main(String[] args) {
        Thread1 thread1 = new Thread1();
        Thread2 thread2 = new Thread2();
        thread1.start();
        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        thread2.start();
    }
    static class Thread1 extends Thread{
        @Override
        public void run() {
            synchronized (object) {
                try {
                    object.wait();
                } catch (InterruptedException e) {
                }
                System.out.println("線程"+Thread.currentThread().getName()+"獲取到了鎖");
            }
        }
    }
    static class Thread2 extends Thread{
        @Override
        public void run() {
            synchronized (object) {
                object.notify();
                System.out.println("線程"+Thread.currentThread().getName()+"調(diào)用了object.notify()");
            }
            System.out.println("線程"+Thread.currentThread().getName()+"釋放了鎖");
        }
    }
}

運行結(jié)果

線程Thread-1調(diào)用了object.notify()
線程Thread-1釋放了鎖
線程Thread-0獲取到了鎖       

方法二

  • Condition是在java 1.5中才出現(xiàn)的,它用來替代傳統(tǒng)的Object的wait()、notify()實現(xiàn)線程間的協(xié)作,相比使用Object的wait()、notify(),使用Condition1的await()、signal()這種方式實現(xiàn)線程間協(xié)作更加安全和高效
  • Condition是個接口,基本的方法就是await()和signal()方法
  • Condition依賴于Lock接口,生成一個Condition的基本代碼是lock.newCondition()
  • 調(diào)用Condition的await()和signal()方法,都必須在lock保護之內(nèi),就是說必須在lock.lock()和lock.unlock之間才可以使用

示例

public class Test {
    private int queueSize = 10;
    private PriorityQueue<Integer> queue = new PriorityQueue<Integer>(queueSize);
    private Lock lock = new ReentrantLock();
    private Condition notFull = lock.newCondition();
    private Condition notEmpty = lock.newCondition();
    public static void main(String[] args)  {
        Test test = new Test();
        Producer producer = test.new Producer();
        Consumer consumer = test.new Consumer();
        producer.start();
        consumer.start();
    }
    class Consumer extends Thread{
        @Override
        public void run() {
            consume();
        }
        private void consume() {
            while(true){
                lock.lock();
                try {
                    while(queue.size() == 0){
                        try {
                            System.out.println("隊列空,等待數(shù)據(jù)");
                            notEmpty.await();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    queue.poll();                //每次移走隊首元素
                    notFull.signal();
                    System.out.println("從隊列取走一個元素,隊列剩余"+queue.size()+"個元素");
                } finally{
                    lock.unlock();
                }
            }
        }
    }
    class Producer extends Thread{
        @Override
        public void run() {
            produce();
        }
        private void produce() {
            while(true){
                lock.lock();
                try {
                    while(queue.size() == queueSize){
                        try {
                            System.out.println("隊列滿,等待有空余空間");
                            notFull.await();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    queue.offer(1);        //每次插入一個元素
                    notEmpty.signal();
                    System.out.println("向隊列取中插入一個元素,隊列剩余空間:"+(queueSize-queue.size()));
                } finally{
                    lock.unlock();
                }
            }
        }
    }
}

到此這篇關(guān)于Java線程協(xié)作的兩種方式小結(jié)的文章就介紹到這了,更多相關(guān)Java線程協(xié)作內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • struts2開發(fā)流程及詳細配置

    struts2開發(fā)流程及詳細配置

    這篇文章主要介紹了struts2開發(fā)流程及詳細配置,步驟比較詳細,具有一定參考價值,需要的朋友可以了解下。
    2017-09-09
  • IDEA 配合 Dockerfile 部署 SpringBoot 工程的注意事項

    IDEA 配合 Dockerfile 部署 SpringBoot 工程的注意事項

    這篇文章主要介紹了IDEA 配合 Dockerfile 部署 SpringBoot 工程,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-09-09
  • SpringBoot 如何編寫配置文件

    SpringBoot 如何編寫配置文件

    這篇文章主要介紹了SpringBoot 編寫配置文件的兩種方法,幫助大家更好的理解和使用springboot框架,感興趣的朋友可以了解下
    2020-11-11
  • java如何更改數(shù)據(jù)庫中的數(shù)據(jù)

    java如何更改數(shù)據(jù)庫中的數(shù)據(jù)

    這篇文章主要介紹了java如何更改數(shù)據(jù)庫中的數(shù)據(jù),修改數(shù)據(jù)庫是數(shù)據(jù)庫操作必不可少的一部分,使用Statement接口中的excuteUpdate()方法可以修改數(shù)據(jù)表中的數(shù)據(jù),感興趣的朋友跟隨小編一起看看吧
    2021-11-11
  • Java解決刪除字符使頻率相同問題

    Java解決刪除字符使頻率相同問題

    給你一個下標從0開始的字符串 word ,字符串只包含小寫英文字母,你需要選擇一個下標并刪除下標處的字符,使得word中剩余每個字母出現(xiàn)頻率相同,本文給大家介紹了Java解決刪除字符使頻率相同問題,需要的朋友可以參考下
    2024-02-02
  • 使用Spring?Boot如何限制在一分鐘內(nèi)某個IP只能訪問10次

    使用Spring?Boot如何限制在一分鐘內(nèi)某個IP只能訪問10次

    有些時候,為了防止我們上線的網(wǎng)站被攻擊,或者被刷取流量,我們會對某一個ip進行限制處理,這篇文章,我們將通過Spring?Boot編寫一個小案例,來實現(xiàn)在一分鐘內(nèi)同一個IP只能訪問10次,感興趣的朋友一起看看吧
    2023-10-10
  • Maven構(gòu)建生命周期詳細介紹

    Maven構(gòu)建生命周期詳細介紹

    這篇文章主要介紹了Maven構(gòu)建生命周期詳細介紹,小編覺得還是挺不錯的,這里分享給大家,需要的朋友可以參考下。
    2017-11-11
  • Java線程公平鎖和非公平鎖的差異講解

    Java線程公平鎖和非公平鎖的差異講解

    今天小編就為大家分享一篇關(guān)于Java線程公平鎖和非公平鎖的差異講解,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-01-01
  • SSH原理及兩種登錄方法圖文詳解

    SSH原理及兩種登錄方法圖文詳解

    SSH(Secure Shell)是一套協(xié)議標準,可以用來實現(xiàn)兩臺機器之間的安全登錄以及安全的數(shù)據(jù)傳送,其保證數(shù)據(jù)安全的原理是非對稱加密。本文通過圖文并茂的形式給大家介紹了SSH原理及兩種登錄方法,一起看看吧
    2018-08-08
  • 支票金額大寫轉(zhuǎn)換示例(金額大寫轉(zhuǎn)換器)

    支票金額大寫轉(zhuǎn)換示例(金額大寫轉(zhuǎn)換器)

    這篇文章主要介紹了支票金額大寫轉(zhuǎn)換示例(金額大寫轉(zhuǎn)換器),需要的朋友可以參考下
    2014-02-02

最新評論

庆云县| 桃园县| 金乡县| 鄂托克旗| 宁陕县| 正宁县| 阳东县| 蒙自县| 呈贡县| 商丘市| 江永县| 万年县| 大足县| 沁源县| 临潭县| 塔河县| 河北区| 宿迁市| 芜湖县| 洛扎县| 神木县| 屏南县| 马龙县| 甘谷县| 天长市| 自治县| 唐河县| 房山区| 湖州市| 东乡县| 广南县| 年辖:市辖区| 南溪县| 垫江县| 湖口县| 沅江市| 墨竹工卡县| 衢州市| 延川县| 甘南县| 赤峰市|