亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Java五種方式實(shí)現(xiàn)多線程循環(huán)打印問(wèn)題

 更新時(shí)間:2021年12月14日 10:57:37   作者:北城酒卿  
本文主要介紹了Java五種方式實(shí)現(xiàn)多線程循環(huán)打印問(wèn)題,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

三個(gè)線程T1、T2、T3輪流打印ABC,打印n次,如ABCABCABCABC…
N個(gè)線程循環(huán)打印1-100…

wait-notify

循環(huán)打印問(wèn)題可以通過(guò)設(shè)置目標(biāo)值,每個(gè)線程想打印目標(biāo)值,如果拿到鎖后這次輪到的數(shù)不是它想要的就進(jìn)入wait

class Wait_Notify_ABC {
    private int num;
    private static final Object Lock = new Object();

    private void print_ABC(int target) {
        synchronized (Lock) {
            //循環(huán)打印
            for (int i = 0; i < 10; i++) {
                while (num % 3 != target) {
                    try {
                        Lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                num++;
                System.out.print(Thread.currentThread().getName());
                Lock.notifyAll();
            }
        }
    }

    public static void main(String[] args) {
        Wait_Notify_ABC wait_notify_abc = new Wait_Notify_ABC();
        new Thread(() -> {
            wait_notify_abc.print_ABC(0);
        }, "A").start();
        new Thread(() -> {
            wait_notify_abc.print_ABC(1);
        }, "B").start();
        new Thread(() -> {
            wait_notify_abc.print_ABC(2);
        }, "C").start();
    }
}

打印1-100問(wèn)題可以理解為有個(gè)全局計(jì)數(shù)器記錄當(dāng)前打印到了哪個(gè)數(shù),其它就和循環(huán)打印ABC問(wèn)題相同。

class Wait_Notify_100 {

    private int num;
    private static final Object LOCK = new Object();
    private int maxnum = 100;

    private void printABC(int targetNum) {
        while (true) {
            synchronized (LOCK) {
                while (num % 3 != targetNum) {
                    if (num >= maxnum) {
                        break;
                    }
                    try {
                        LOCK.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                if (num >= maxnum) {
                    break;
                }
                num++;
                System.out.println(Thread.currentThread().getName() + ": " + num);
                LOCK.notifyAll();
            }
        }

    }

    public static void main(String[] args) {
        Wait_Notify_100 wait_notify_100 = new Wait_Notify_100();
        new Thread(() -> {
            wait_notify_100.printABC(0);
        }, "thread1").start();
        new Thread(() -> {
            wait_notify_100.printABC(1);
        }, "thread2").start();
        new Thread(() -> {
            wait_notify_100.printABC(2);
        }, "thread3").start();
    }
}

join方式

一個(gè)線程內(nèi)調(diào)用另一個(gè)線程的join()方法可以讓另一個(gè)線程插隊(duì)執(zhí)行,比如Main方法里調(diào)用了A.join(),那么此時(shí)cpu會(huì)去執(zhí)行A線程中的任務(wù),執(zhí)行完后再看Main是否能搶到運(yùn)行權(quán)。所以對(duì)于ABC,我們可以對(duì)B說(shuō)讓A插隊(duì),對(duì)C說(shuō)讓B插隊(duì)

class Join_ABC {
    static class printABC implements Runnable {
        private Thread beforeThread;

        public printABC(Thread beforeThread) {
            this.beforeThread = beforeThread;
        }

        @Override
        public void run() {
            if (beforeThread != null) {
                try {
                    beforeThread.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.print(Thread.currentThread().getName());
        }
    }

    public static void main(String[] args) throws InterruptedException {
        for (int i = 0; i < 10; i++) {
            Thread t1 = new Thread(new printABC(null), "A");
            Thread t2 = new Thread(new printABC(t1), "B");
            Thread t3 = new Thread(new printABC(t2), "C");
            t1.start();
            t2.start();
            t3.start();
            Thread.sleep(100);
        }
    }
}

ReentrantLock

同理,synchronized和reentrantlock都是我們常用的加鎖方式,不過(guò)后者可以中斷,可以實(shí)現(xiàn)公平鎖,可以使用condition…但是需要我們手動(dòng)釋放鎖。jdk8后二者性能差不多,畢竟synchronized有鎖升級(jí)的過(guò)程嘛。

class ReentrantLock_ABC {

    private int num;   
    private Lock lock = new ReentrantLock();

    private void printABC(int targetNum) {
        for (int i = 0; i < 100; ) {
            lock.lock();
            if (num % 3 == targetNum) {
                num++;
                i++;
                System.out.print(Thread.currentThread().getName());
            }
            lock.unlock();
        }
    }

    public static void main(String[] args) {
        Lock_ABC lockABC = new Lock_ABC();

        new Thread(() -> {
            lockABC.printABC(0);
        }, "A").start();

        new Thread(() -> {
            lockABC.printABC(1);
        }, "B").start();

        new Thread(() -> {
            lockABC.printABC(2);
        }, "C").start();
    }
}

ReentrantLock+Condition

以上方式如果線程搶到鎖后發(fā)現(xiàn)自己無(wú)法執(zhí)行任務(wù),那么就釋放,然后別的線程再搶占再看是不是自己的…這種方式比較耗時(shí),如果我們能實(shí)現(xiàn)精準(zhǔn)喚醒鎖呢,即A完成任務(wù)后喚醒它的下一個(gè)即B,這就用到我們的Condition啦

class ReentrantLock_Condition_ABC {

    private int num;
    private static Lock lock = new ReentrantLock();
    private static Condition c1 = lock.newCondition();
    private static Condition c2 = lock.newCondition();
    private static Condition c3 = lock.newCondition();

    private void printABC(int targetNum, Condition currentThread, Condition nextThread) {
        for (int i = 0; i < 100; ) {
            lock.lock();
            try {
                while (num % 3 != targetNum) {
                    currentThread.await();  //阻塞當(dāng)前線程
                }
                num++;
                i++;
                System.out.print(Thread.currentThread().getName());
                nextThread.signal();    //喚醒下一個(gè)線程
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    }

    public static void main(String[] args) {
        ReentrantLock_Condition_ABC reentrantLockConditionAbc = new ReentrantLock_Condition_ABC();
        new Thread(() -> {
            reentrantLockConditionAbc.printABC(0, c1, c2);
        }, "A").start();
        new Thread(() -> {
            reentrantLockConditionAbc.printABC(1, c2, c3);
        }, "B").start();
        new Thread(() -> {
            reentrantLockConditionAbc.printABC(2, c3, c1);
        }, "C").start();
    }
}

Semaphore

小伙伴們有沒有想到過(guò),在生產(chǎn)者消費(fèi)者模型中我們有哪幾種實(shí)現(xiàn)方式呢?wait\notify,ReentrantLock,Semaphone,阻塞隊(duì)列,管道輸入輸出流。
對(duì)的就是Semaphone。
Semaphore有acquire方法和release方法。 當(dāng)調(diào)用acquire方法時(shí)線程就會(huì)被阻塞,直到獲得許可證為止。 當(dāng)調(diào)用release方法時(shí)將向Semaphore中添加一個(gè)許可證。如果沒有獲取許可證的線程, Semaphore只是記錄許可證的可用數(shù)量。
使用Semaphore也可以實(shí)現(xiàn)精準(zhǔn)喚醒。

class SemaphoreABC {

    private static Semaphore s1 = new Semaphore(1); //因?yàn)橄葓?zhí)行線程A,所以這里設(shè)s1的計(jì)數(shù)器為1
    private static Semaphore s2 = new Semaphore(0);
    private static Semaphore s3 = new Semaphore(0);

    private void printABC(Semaphore currentThread, Semaphore nextThread) {
        for (int i = 0; i < 10; i++) {
            try {
                currentThread.acquire();       //阻塞當(dāng)前線程,即信號(hào)量的計(jì)數(shù)器減1為0
                System.out.print(Thread.currentThread().getName());
                nextThread.release();          //喚醒下一個(gè)線程,即信號(hào)量的計(jì)數(shù)器加1
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        SemaphoreABC printer = new SemaphoreABC();
        new Thread(() -> {
            printer.printABC(s1, s2);
        }, "A").start();
        Thread.sleep(100);
        new Thread(() -> {
            printer.printABC(s2, s3);
        }, "B").start();
        Thread.sleep(100);
        new Thread(() -> {
            printer.printABC(s3, s1);
        }, "C").start();
    }
}

到此這篇關(guān)于Java五種方式實(shí)現(xiàn)多線程循環(huán)打印問(wèn)題的文章就介紹到這了,更多相關(guān)Java 多線程循環(huán)打印內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java中Color和16進(jìn)制字符串互相轉(zhuǎn)換的方法

    Java中Color和16進(jìn)制字符串互相轉(zhuǎn)換的方法

    這篇文章主要給大家介紹了關(guān)于Java中Color和16進(jìn)制字符串互相轉(zhuǎn)換的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2018-07-07
  • 零基礎(chǔ)寫Java知乎爬蟲之進(jìn)階篇

    零基礎(chǔ)寫Java知乎爬蟲之進(jìn)階篇

    前面幾篇文章,我們都是簡(jiǎn)單的實(shí)現(xiàn)了java爬蟲抓取內(nèi)容的問(wèn)題,那么如果遇到復(fù)雜情況,我們還能繼續(xù)那么做嗎?答案當(dāng)然是否定的,之前的僅僅是入門篇,都是些基礎(chǔ)知識(shí),給大家練手用的,本文我們就來(lái)點(diǎn)高大上的東西
    2014-11-11
  • SpringBoot使用thymeleaf實(shí)現(xiàn)前端表格

    SpringBoot使用thymeleaf實(shí)現(xiàn)前端表格

    雖然現(xiàn)在流行前后端分離,但是后端模版在一些關(guān)鍵地方還是非常有用的,例如郵件模版、代碼模版等。當(dāng)然也不排除一些古老的項(xiàng)目后端依然使用動(dòng)態(tài)模版。Thymeleaf 簡(jiǎn)潔漂亮、容易理解,并且完美支持 HTML5,可以直接打開靜態(tài)頁(yè)面,同時(shí)不新增標(biāo)簽,只需增強(qiáng)屬性
    2022-10-10
  • SystemServer進(jìn)程啟動(dòng)過(guò)程解析

    SystemServer進(jìn)程啟動(dòng)過(guò)程解析

    這篇文章主要為大家介紹了SystemServer進(jìn)程啟動(dòng)過(guò)程解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-07-07
  • Java中的SpringAOP、代理模式、常用AspectJ注解詳解

    Java中的SpringAOP、代理模式、常用AspectJ注解詳解

    這篇文章主要介紹了Java中的SpringAOP、代理模式、常用AspectJ注解詳解,Spring提供了面向切面編程的豐富支持,允許通過(guò)分離應(yīng)用的業(yè)務(wù)邏輯與系統(tǒng)級(jí)服務(wù),例如審計(jì)和事務(wù)管理進(jìn)行內(nèi)聚性的開發(fā),需要的朋友可以參考下
    2023-09-09
  • 淺談SpringCache與redis集成實(shí)現(xiàn)緩存解決方案

    淺談SpringCache與redis集成實(shí)現(xiàn)緩存解決方案

    本篇文章主要介紹了淺談SpringCache與redis集成實(shí)現(xiàn)緩存解決方案,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-12-12
  • Maven中生命周期的具體使用

    Maven中生命周期的具體使用

    在 Maven 出現(xiàn)之前,項(xiàng)目構(gòu)建的生命周期就已經(jīng)存在,本文主要介紹了Maven中生命周期的具體使用,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-09-09
  • Java?9中的"菱形"語(yǔ)法詳解

    Java?9中的"菱形"語(yǔ)法詳解

    Java?9?再次增強(qiáng)了“菱形”語(yǔ)法,它甚至允許在創(chuàng)建匿名內(nèi)部類時(shí)使用菱形語(yǔ)法,Java?可根據(jù)上下文來(lái)推斷匿名內(nèi)部類中泛型的類型,下面程序示范了在匿名內(nèi)部類中使用菱形語(yǔ)法,感興趣的朋友跟隨小編一起看看吧
    2023-06-06
  • Spring實(shí)戰(zhàn)之使用靜態(tài)工廠方法創(chuàng)建Bean操作示例

    Spring實(shí)戰(zhàn)之使用靜態(tài)工廠方法創(chuàng)建Bean操作示例

    這篇文章主要介紹了Spring實(shí)戰(zhàn)之使用靜態(tài)工廠方法創(chuàng)建Bean操作,結(jié)合實(shí)例形式分析了靜態(tài)工廠方法創(chuàng)建Bean的相關(guān)實(shí)現(xiàn)步驟與操作注意事項(xiàng),需要的朋友可以參考下
    2019-11-11
  • springboot項(xiàng)目打成jar包后無(wú)法獲取static下的靜態(tài)資源文件的問(wèn)題分析

    springboot項(xiàng)目打成jar包后無(wú)法獲取static下的靜態(tài)資源文件的問(wèn)題分析

    這篇文章主要介紹了springboot項(xiàng)目打成jar包后無(wú)法獲取static下的靜態(tài)資源文件的問(wèn)題分析,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-08-08

最新評(píng)論