Java多线程:交替打印字符串

Java多线程:交替打印字符串

问题

在这里插入图片描述

方法

1.CyclicBarrier

  首先需要知道,每个数字对应调用四个方法中的某一个打印语句。对于四个方法,我们可以使其依次遍历1~n,但我们需要满足从小到大按序打印,由于线程运行的速度有快有慢,那么我们必须得建立一个基准,我们可以使用CyclicBarrier让四个线程每次从同一起跑线出发。也就是说我们只需要让四个线程调用的四个方法同时判断同一个数字即可,先判断完的等待后判断完的,四个方法都判断完后再判断下一个数字,利用CyclicBarrier可以实现这一点

代码:
    class FizzBuzz {
   
        private int n;

        public FizzBuzz(int n) {
   
            this.n = n;
        }
        
        public CyclicBarrier cyclicBarrier = new CyclicBarrier(4);
        
        // printFizz.run() outputs "fizz".
        public void fizz(Runnable printFizz) throws InterruptedException {
   
            int i;
            for (i = 1;i <= n;i++) {
   
                if (i % 3 == 0 && i % 5 != 0) {
   
                    printFizz.run();
                }
                try {
   
                    cyclicBarrier.await();
                } catch (BrokenBarrierException e) {
   
                    e.printStackTrace();
                }
            }
        }

        // printBuzz.run() outputs "buzz".
        public void buzz(Runnable printBuzz) throws InterruptedException {
   
            int i;
            for (i = 1;i <= n;i++) {
   
                if (i % 5 == 0 && i % 3 != 0) {
   
                    printBuzz.run();
                }
                try {
   
                    cyclicBarrier.await();
                } catch (BrokenBarrierException e) {
   
                    e.printStackTrace();
                }
            }
        }

        // printFizzBuzz.run() outputs "fizzbuzz".
        public void fizzbuzz(Runnable printFizzBuzz) throws InterruptedException {
   
            int i;
            for (i = 1;i <= n;i++) {
   
                if (i % 5 == 0 && i % 3 == 0) {
   
                    printFizzBuzz.run();
                }
                try {
   
                    cyclicBarrier.await();
                } catch (BrokenBarrierException e) {
   
                    e.printStackTrace();
                }
            }
        }

        // printNumber.accept(x) outputs "x", where x is an integer.
        public void number(IntConsumer printNumber) throws InterruptedException {
   
            int i;
            for (i = 1;i <= n;i++) {
   
                if (i % 5 != 0 && i % 3 != 0) {
   
                    printNumber.accept(i);
                }
                try {
   
                    cyclicBarrier.await();
                } catch (BrokenBarrierException e) {
   
                    e.printStackTrace();
                }
            }
        }
    }
2.Semaphore

  首先需要知道,每个数字对应调用四个方法中的某一个打印语句。对于四个方法,我们可以使其依次遍历1~n,但我们需要满足从小到大按序打印。由于线程运行的速度有快有慢,那么我们必须得建立一个基准,这里我们可以使用信号量让四个线程以执行number方法的线程为基准,当某个线程运行速度快于基准线程时,若它要进行打印,我们让其等待基准线程向其发送信号,才能进行打印。同时需要注意,我们也得控制基准线程的步伐,基准线程需等待其他线程打印完成之后,才能进行下一次判断,否则若基准线程过快,可能其他线程还没打印,基准线程就打印了多次。
  我们使用信号量fizzbuzzRun,buzzRun,fizzRun分别表示用于控制fizzbuzz,buzz,fizz方法对应线程速度的信号量,初始值为0,在打印前,必须获得对应的信号量,而信号量由number方法release,因此若这三个线程速度较快,也不会提前输出,而是会等待number方法对应的线程向其发送信号。使用信号量number用于控制number方法对应线程的速度,初始值为1,在对当前遍历的数字进行整除判断前,需要获得number信号量,number信号量一方面是在其他三个线程打印完成后release的,另一方面是在number方法打印完成后release的,也就是进行一次打印后都要释放number信号量,这样才能保证number方法能顺利进行下一个数字的判断。

代码:
    class FizzBuzz {
   
        private int n;

        public FizzBuzz(int n) {
   
            this.n = n;
        }

        public Semaphore fizzbuzzRun = new Semaphore(0)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

happy19991001

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值