LeetCode刷题之旅【多线程篇-4】中等: 1116. 打印零与奇偶数

 

2019年11月22日

目录

题目:1116. 打印零与奇偶数

解题1:Semaphore 信号量作屏障

解题2:synchronized独占锁+线程阻塞与唤醒

拓展


题目:1116. 打印零与奇偶数

 

解题1:Semaphore 信号量作屏障

class ZeroEvenOdd {
    private int n;
    private static Semaphore z = new Semaphore(1);
	private static Semaphore e = new Semaphore(0);
	private static Semaphore o = new Semaphore(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 {
		for (int i=1; i<=n; i++){
			z.acquire();
			printNumber.accept(0);
			if ((i&1)==0){
				e.release();
			} else {
				o.release();
			}
		}
	}

	/**
	 * 输出偶数
	 */
	public void even(IntConsumer printNumber) throws InterruptedException {
		for (int i=2; i<=n; i+=2){
			e.acquire();
			printNumber.accept(i);
			z.release();
		}
	}

	/**
	 * 输出奇数
	 */
	public void odd(IntConsumer printNumber) throws InterruptedException {
		for (int i=1; i<=n; i+=2){
			o.acquire();
			printNumber.accept(i);
			z.release();
		}
	}
}

解题2:synchronized独占锁+线程阻塞与唤醒

class ZeroEvenOdd {
    private int n;
    private boolean first;
    private boolean second;
    private boolean zoo = true;
    
    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){
            for(int i=1;i<=n;i++){
                 while(!zoo){
                    this.wait();
                 }   
                printNumber.accept(0);
                zoo = false;
                if(i%2!=0){
                    first = true;
                }else{
                    second = true;
                }
                this.notifyAll();
            }
        }
    }

    public void even(IntConsumer printNumber) throws InterruptedException {
        synchronized(this){
            for(int i=2;i<=n;i+=2){
                while(!second){
                    this.wait();
                }
                printNumber.accept(i);
                second = false;
                zoo = true;
                this.notifyAll();
            }
        }

    }

    public void odd(IntConsumer printNumber) throws InterruptedException {
        synchronized(this){
            for(int i=1;i<=n;i+=2){
                
                while(!first){
                    this.wait();
                }
                printNumber.accept(i);
                first = false;
                zoo = true;
                this.notifyAll();
            }
        }

    }
}

 

拓展

  • 信号量的初始值有何讲究?0?1?-1?

If the value is positive, then it represents the number of threads that can decrement without blocking. If it is negative, then it represents the number of threads that have blocked and are waiting. If the value is zero, it means there are no threads waiting, but if a thread tries to decrement, it will block.

如果该值为正,则表示可以在不阻塞的情况下减少的线程数。

如果为负,则表示已阻塞且正在等待的线程数。

如果该值为零,则表示没有线程在等待,但如果线程尝试递减,则它将阻塞。

  • IntConsumer 是什么编程手法?

Consumer是java8提供的函数式接口之一,意思为消费者,接受参数而不返回值。

Consumer还有多个其他的接口,具体有以下几种,在使用函数式接口时,若有提供具体类型的接口,就尽量使用此接口,因为具体的类型指定可以避免装箱拆箱时所带来的额外资源消耗

参考:https://zhuanlan.zhihu.com/p/81626432


欢迎扫二维码关注公众号,获取技术干货

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值