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

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

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

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

wait-notify

循環(huán)打印問題可以通過設置目標值,每個線程想打印目標值,如果拿到鎖后這次輪到的數(shù)不是它想要的就進入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問題可以理解為有個全局計數(shù)器記錄當前打印到了哪個數(shù),其它就和循環(huán)打印ABC問題相同。

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方式

一個線程內調用另一個線程的join()方法可以讓另一個線程插隊執(zhí)行,比如Main方法里調用了A.join(),那么此時cpu會去執(zhí)行A線程中的任務,執(zhí)行完后再看Main是否能搶到運行權。所以對于ABC,我們可以對B說讓A插隊,對C說讓B插隊

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都是我們常用的加鎖方式,不過后者可以中斷,可以實現(xiàn)公平鎖,可以使用condition…但是需要我們手動釋放鎖。jdk8后二者性能差不多,畢竟synchronized有鎖升級的過程嘛。

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)自己無法執(zhí)行任務,那么就釋放,然后別的線程再搶占再看是不是自己的…這種方式比較耗時,如果我們能實現(xiàn)精準喚醒鎖呢,即A完成任務后喚醒它的下一個即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();  //阻塞當前線程
                }
                num++;
                i++;
                System.out.print(Thread.currentThread().getName());
                nextThread.signal();    //喚醒下一個線程
            } 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

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

class SemaphoreABC {

    private static Semaphore s1 = new Semaphore(1); //因為先執(zhí)行線程A,所以這里設s1的計數(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();       //阻塞當前線程,即信號量的計數(shù)器減1為0
                System.out.print(Thread.currentThread().getName());
                nextThread.release();          //喚醒下一個線程,即信號量的計數(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();
    }
}

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

相關文章

  • Kafka中Producer和Consumer的作用詳解

    Kafka中Producer和Consumer的作用詳解

    這篇文章主要介紹了Kafka中Producer和Consumer的作用詳解,Kafka是一個分布式的流處理平臺,它的核心是消息系統(tǒng),Producer是Kafka中用來將消息發(fā)送到Broker的組件之一,它將消息發(fā)布到主題,并且負責按照指定的分區(qū)策略將消息分配到對應的分區(qū)中,需要的朋友可以參考下
    2023-12-12
  • Java讀寫文件創(chuàng)建文件夾多種方法示例詳解

    Java讀寫文件創(chuàng)建文件夾多種方法示例詳解

    這篇文章主要介紹了Java讀寫文件創(chuàng)建文件夾等多種操作的方法,大家參考使用吧
    2013-11-11
  • Java Lambda 表達式源碼解析

    Java Lambda 表達式源碼解析

    這篇文章主要介紹了Java Lambda在JVM中是如何實現(xiàn)的,感興趣的小伙伴一起來了解了解
    2021-08-08
  • Java實現(xiàn)冒泡排序算法及對其的簡單優(yōu)化示例

    Java實現(xiàn)冒泡排序算法及對其的簡單優(yōu)化示例

    這篇文章主要介紹了Java實現(xiàn)冒泡排序算法及對其的簡單優(yōu)化示例,冒泡排序的最差時間復雜度為O(n^2),最優(yōu)時間復雜度為O(n),存在優(yōu)化的余地,需要的朋友可以參考下
    2016-05-05
  • Springboot使用redis實現(xiàn)接口Api限流的示例代碼

    Springboot使用redis實現(xiàn)接口Api限流的示例代碼

    本文主要介紹了Springboot使用redis實現(xiàn)接口Api限流的示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-07-07
  • 淺談web項目讀取classpath路徑下面的文件

    淺談web項目讀取classpath路徑下面的文件

    這篇文章主要介紹了淺談web項目讀取classpath路徑下面的文件,具有一定借鑒價值,需要的朋友可以參考下
    2018-01-01
  • SpringBoot獲取Request請求的三種方式小結

    SpringBoot獲取Request請求的三種方式小結

    本文介紹了SpringBoot中獲取Request對象的三種方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2024-12-12
  • 阿里云OSS域名配置及簡單上傳的示例代碼

    阿里云OSS域名配置及簡單上傳的示例代碼

    這篇文章主要介紹了阿里云OSS域名配置及簡單上傳的示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-08-08
  • quarzt定時調度任務解析

    quarzt定時調度任務解析

    這篇文章主要介紹了quarzt定時調度任務,具有一定參考價值,需要的朋友可以了解下。
    2017-12-12
  • Spring Boot整合ElasticSearch實現(xiàn)多版本兼容的方法詳解

    Spring Boot整合ElasticSearch實現(xiàn)多版本兼容的方法詳解

    簡單說,ElasticSearch(簡稱 ES)是搜索引擎,是結構化數(shù)據(jù)的分布式搜索引擎。下面這篇文章主要給大家介紹了關于Spring Boot整合ElasticSearch實現(xiàn)多版本兼容的相關資料,需要的朋友可以參考借鑒,下面來一起看看吧
    2018-05-05

最新評論

永川市| 准格尔旗| 方正县| 塘沽区| 山西省| 锡林郭勒盟| 彰化市| 鄂托克旗| 彰武县| 满城县| 隆尧县| 清河县| 迁西县| 博客| 阿图什市| 稻城县| 内黄县| 东辽县| 蒲城县| 丹江口市| 石城县| 巴里| 平塘县| 淮北市| 大姚县| 神农架林区| 阿城市| 揭阳市| 葫芦岛市| 墨竹工卡县| 九寨沟县| 云浮市| 宁强县| 上饶县| 宜宾县| 巨鹿县| 沭阳县| 雷波县| 伊宁县| 翁牛特旗| 南漳县|