阿里面试题:手写两个线程一个线程打印1,一个线程打印0,依次交替

阿里一面上来就让手写一个多线程模型,利用condition来实现1和0的交替执行,着实把我弄懵逼了,凭借着自己微弱的记忆,大致写出了如下:
基本思路是:
1、线程 操作 (方法) 资源类
2、判断 干活 通知
3、利用while判断来防止虚假唤醒机制

第一种方法利用Lock进行加锁解锁:

public class ProducerAndConsumer {
    public static void main(String[] args) {
        Food food = new Food();
        new Thread(()->{
            for (int i = 0; i < 100; i++) {
                try {
                    food.produce();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        },"生产者").start();



        new Thread(()->{
            for (int i = 0; i < 100; i++) {
                try {
                    food.consumer();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        },"消费者").start();
    }
}

/**
 * 线程操作的资源
 */
class Food{

    private int number = 0;

    private Lock lock = new ReentrantLock();
    private Condition condition = lock.newCondition();

    /**
     * 打印1
     * @throws Exception
     */
    public void produce() throws Exception{
        lock.lock();
        try {
            // 1. number等于0,才开始生产,不等于0,则生产者处于等待状态

            // 这里必须用while判断,否则可能产生虚假唤醒
            while(number != 0){
                condition.await();
            }
            // 2. 等于0,则开始干活
            number++;
            System.out.println("生产者生产.... " + number);

            // 3. 生产者生产完了之后,需要通知唤醒消费者
            condition.signalAll();
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }

    /**
     * 打印0
     * @throws Exception
     */
    public void consumer() throws Exception{
        lock.lock();
        try {
            // 1. number ==0 ,生产者等待
            while(number == 0){
                condition.await();
            }

            // 2. 如果number != 0,则消费者消费
            number--;
            System.out.println("消费者消费.... " + number);

            // 3. 消费者消费之后,通知唤醒生产者
            condition.signalAll();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }
}

方法二:利用Synchronized关键字进行加锁解锁:

public class Juc013WaitNotify {

    static int number = 0;
    static Object object = new Object();

    public static void main(String[] args) throws Exception{

        Thread one = new Thread(new PrintOne(),"PrintOne");
        one.start();
        TimeUnit.SECONDS.sleep(1);
        Thread zero = new Thread(new printZero(),"PrintTwo");

        zero.start();
    }

    /**
     * 打印1
     */
    static class PrintOne implements Runnable{
        
        @Override
        public void run(){
            for(int i = 0;i < 100;i++){
                // 进来操作之前,先加锁
                synchronized (object){
                    while(number == 0){
                        try {
                            object.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }

                    System.out.println("---------------打印1---------------");
                    number = 0;
                    object.notifyAll();
                }
            }

        }
    }



    static class printZero implements Runnable{
        @Override
        public void run() {
            for(int i = 0;i < 100;i++){
                synchronized (object){
                    while (number == 1){
                        try {
                            object.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.println("---------------打印0---------------");
                    number = 1;
                    object.notifyAll();
                }
            }
        }
    }
}

基本的处理逻辑:
等待方遵循的原则:

  1. 获取对象的锁
  2. 如果条件不满足,则调用对象的wait()方法,被通知后仍然要检查条件
  3. 条件满足才执行相应的业务
    大致的代码为:
synchronized(对象){
	while(条件不满足){
		对象.wait()
	}
	// 条件满足,则执行相应的逻辑
	……………………
}

通知方的工作:

  1. 获取对象的锁
  2. 改变对象
  3. 通知等待在对象上的线程
synchronized(对象){
	改变条件
	对象.notifyAll()
}
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值