• [Java]LeetCode1116. 打印零与奇偶数 | Print Zero Even Odd


    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
    ➤微信公众号:山青咏芝(shanqingyongzhi)
    ➤博客园地址:山青咏芝(https://www.cnblogs.com/strengthen/
    ➤GitHub地址:https://github.com/strengthen/LeetCode
    ➤原文地址:
    ➤如果链接不是山青咏芝的博客园地址,则可能是爬取作者的文章。
    ➤原文已修改更新!强烈建议点击原文地址阅读!支持作者!支持原创!
    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★

    Suppose you are given the following code:

    class ZeroEvenOdd {
      public ZeroEvenOdd(int n) { ... }  // constructor
    public void zero(printNumber) { ... } // only output 0's
    public void even(printNumber) { ... } // only output even numbers
    public void odd(printNumber) { ... } // only output odd numbers
    }
    The same instance of ZeroEvenOdd will be passed to three different threads:

    Thread A will call zero() which should only output 0's.
    Thread B will call even() which should only ouput even numbers.
    Thread C will call odd() which should only output odd numbers.
    Each of the thread is given a printNumber method to output an integer. Modify the given program to output the series 010203040506... where the length of the series must be 2n.

    Example 1:

    Input: n = 2
    Output: "0102"
    Explanation: There are three threads being fired asynchronously. One of them calls zero(), the other calls even(), and the last one calls odd(). "0102" is the correct output.
    Example 2:

    Input: n = 5
    Output: "0102030405"


    假设有这么一个类:

    class ZeroEvenOdd {
      public ZeroEvenOdd(int n) { ... }  // 构造函数
    public void zero(printNumber) { ... } // 仅打印出 0
    public void even(printNumber) { ... } // 仅打印出 偶数
    public void odd(printNumber) { ... } // 仅打印出 奇数
    }
    相同的一个 ZeroEvenOdd 类实例将会传递给三个不同的线程:

    线程 A 将调用 zero(),它只输出 0 。
    线程 B 将调用 even(),它只输出偶数。
    线程 C 将调用 odd(),它只输出奇数。
    每个线程都有一个 printNumber 方法来输出一个整数。请修改给出的代码以输出整数序列 010203040506... ,其中序列的长度必须为 2n。

    示例 1:

    输入:n = 2
    输出:"0102"
    说明:三条线程异步执行,其中一个调用 zero(),另一个线程调用 even(),最后一个线程调用odd()。正确的输出为 "0102"。
    示例 2:

    输入:n = 5
    输出:"0102030405"


    4ms

     1 import java.util.concurrent.*;
     2 
     3 class ZeroEvenOdd {
     4     private int n;
     5     Semaphore s1, s2, s3;
     6     
     7     public ZeroEvenOdd(int n) {
     8         this.n = n;
     9         s1 = new Semaphore(1);
    10         s2 = new Semaphore(0);
    11         s3 = new Semaphore(0);
    12     }
    13 
    14     // printNumber.accept(x) outputs "x", where x is an integer.
    15     public void zero(IntConsumer printNumber) throws InterruptedException {
    16         for (int i = 0; i < n; i++) {
    17             s1.acquire();
    18             printNumber.accept(0);
    19             if (i % 2 == 0) {
    20                 s3.release();
    21             } else {
    22                 s2.release();
    23             }
    24         }
    25     }
    26 
    27     public void even(IntConsumer printNumber) throws InterruptedException {
    28         for (int i = 2; i <= n; i += 2) {
    29             s2.acquire();
    30             printNumber.accept(i);
    31             s1.release();
    32         }
    33     }
    34 
    35     public void odd(IntConsumer printNumber) throws InterruptedException {
    36         for (int i = 1; i <= n; i += 2) {
    37             s3.acquire();
    38             printNumber.accept(i);
    39             s1.release();
    40         }
    41     }
    42 }

    7ms

     1 import java.util.concurrent.locks.ReentrantLock;
     2 import java.util.concurrent.locks.Condition;
     3 import java.util.function.IntConsumer;
     4 class ZeroEvenOdd {
     5     private int n;
     6     private ReentrantLock lock = new ReentrantLock();
     7     private Condition z = lock.newCondition();
     8     private Condition e = lock.newCondition();
     9     private Condition o = lock.newCondition();
    10     private boolean isZero = true;
    11     private boolean isOld = true;
    12     public ZeroEvenOdd(int n) {
    13         this.n = n;
    14     }
    15 
    16     // printNumber.accept(x) outputs "x", where x is an integer.
    17     public void zero(IntConsumer printNumber) throws InterruptedException {
    18         lock.lock();
    19         for (int i = 1; i <= n; i++) {
    20             if (!isZero) {
    21                 z.await();
    22             }
    23             printNumber.accept(0);
    24             isZero = false;
    25             if (i%2!=0) {
    26                 o.signal();
    27             } else {
    28                 e.signal();
    29             }
    30         }
    31         lock.unlock();
    32     }
    33 
    34     public void even(IntConsumer printNumber) throws InterruptedException {
    35         lock.lock();
    36         for (int i = 2; i <= n; i+=2) {
    37             if (isZero||isOld) {
    38                 e.await();
    39             }
    40             printNumber.accept(i);
    41             isZero = true;
    42             isOld = true;
    43             z.signal();
    44         }
    45         lock.unlock();
    46     }
    47 
    48     public void odd(IntConsumer printNumber) throws InterruptedException {
    49         lock.lock();
    50         for (int i = 1; i <= n; i+=2) {
    51             if (isZero||!isOld) {
    52                 o.await();
    53             }
    54             printNumber.accept(i);
    55             isZero = true;
    56             isOld=false;
    57             z.signal();
    58         }
    59         lock.unlock();
    60     }
    61 }

    8ms

     1 import java.util.concurrent.locks.*;
     2 class ZeroEvenOdd {
     3     private int n;
     4     private volatile boolean e = false;
     5     private volatile boolean o = false;
     6     private ReentrantLock lock = new ReentrantLock();
     7     private Condition zeroCondition = lock.newCondition();
     8     private Condition evenCondition = lock.newCondition();
     9     private Condition oddCondition = lock.newCondition();
    10 
    11 
    12     public ZeroEvenOdd(int n) {
    13         this.n = n;
    14     }
    15 
    16     // printNumber.accept(x) outputs "x", where x is an integer.
    17     public void zero(IntConsumer printNumber) throws InterruptedException {
    18         for (int i = 1; i <= n; i++) {
    19             lock.lock();
    20             try {
    21                 if (i != 1) {
    22                     zeroCondition.await();
    23                 }
    24                 printNumber.accept(0);
    25                 if (isOdd(i)) {
    26                     o = true;
    27                     oddCondition.signal();
    28                 } else {
    29                     e = true;
    30                     evenCondition.signal();
    31                 }
    32             } finally {
    33                 lock.unlock();
    34             }
    35         }
    36     }
    37 
    38     public void even(IntConsumer printNumber) throws InterruptedException {
    39         for (int i = 2; i <= n; i += 2) {
    40             lock.lock();
    41             try {
    42                 while (!e) {
    43                     evenCondition.await();
    44                 }
    45                 e = false;
    46                 printNumber.accept(i);
    47                 zeroCondition.signal();
    48             } finally {
    49                 lock.unlock();
    50             }
    51         }
    52 
    53     }
    54 
    55     public void odd(IntConsumer printNumber) throws InterruptedException {
    56         for (int i = 1; i <= n; i += 2) {
    57             lock.lock();
    58             try {
    59                 while (!o) {
    60                     oddCondition.await();
    61                 }
    62                 o = false;
    63                 printNumber.accept(i);
    64                 zeroCondition.signal();
    65             } finally {
    66                 lock.unlock();
    67             }
    68         }
    69     }
    70 
    71     private static boolean isOdd(final int number) {
    72         return (number & 1) == 1;
    73     }
    74 }
  • 相关阅读:
    EKLM3S8962之LED
    [uClinuxdev] detecting stack overflow
    Eclipse换行符
    EKLM3S8962之OLED
    Windows 环境下 GNU ARM 开发环境建立
    关于阻焊层和助焊层的理解
    MISRA C 2004中文版
    对话框托盘程序实现源码
    VC++中四种进程或线程同步互斥的控制方法
    Windows线程同步与互斥技术总结
  • 原文地址:https://www.cnblogs.com/strengthen/p/11289223.html
Copyright © 2020-2023  润新知