【多线程】线程同步之wait 和 notify

需求

leetcode 1116. 打印零与奇偶数 奇偶交替打印 
给出一个正整数n,打印出0102.....0n的序列

3个线程共享对象 ZeroEvenOdd,t1 调用其zero();t2 调用odd();t3 调用even()方法

解题思路

Wait-notify模型进行三个线程的同步,两个变量,一个是序列当前数字(包含0),还有一个是递增数字
3个线程都有着个字的打印条件,如果不符合则wait,如果符合则打印,并唤醒其它两个线程。

代码实现

class ZeroEvenOdd {
    private int n;
    volatile private int cur = -1;
    volatile private int num = 0;

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

    // printNumber.accept(x) outputs "x", where x is an integer.
    public void zero(IntConsumer printNumber) throws InterruptedException {
        synchronized (this) {
            while ( num < n) {
                if (cur==0) {
                    wait();
                } else {
                    cur = 0;
                    printNumber.accept(cur);
                    notifyAll();
                }
            }
        }

    }

    public void even(IntConsumer printNumber) throws InterruptedException {
        synchronized (this) {
            while (num < n) {
                if (cur!=0 || (num&1) ==0 ) { //不满足条件 条件是 序列当前为0,且上一个有效数字是奇数
                    wait();
                } else {
                    cur = ++num; //获取下一个偶数
                    printNumber.accept(cur);
                    notifyAll();
                }
            }
        }

    }

    public void odd(IntConsumer printNumber) throws InterruptedException {
        synchronized (this) {
            while (num < n) {

                if (cur!=0 || (num&1) ==1 ) { //不满足条件 条件是 序列当前为0,且上一个有效数字是奇数
                    wait();
                } else {
                    cur = ++num; //获取下一个奇数
                    printNumber.accept(cur);
                    notifyAll();
                }
            }
        }
    }
}

测试验证

    public static void main(String[] args) {
        ExecutorService pool = Executors.newFixedThreadPool(3);
        ZeroEvenOdd zeroEvenOdd = new ZeroEvenOdd(5);
        pool.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    zeroEvenOdd.zero(new print());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        pool.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    zeroEvenOdd.even(new print());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        pool.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    zeroEvenOdd.odd(new print());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

    }
    static class print implements IntConsumer {
        @Override
        public void accept(int value) {
            System.out.print(value);
        }
    }

发布了92 篇原创文章 · 获赞 14 · 访问量 5816

猜你喜欢

转载自blog.csdn.net/sarafina527/article/details/103884887
今日推荐