• 生产者和消费者问题(synchronized、Lock)


    1.synchronized的生产者和消费者
    synchronized是锁住对象
    this.wait()释放了锁 并等待
    
    this.notify()随机通知并唤醒同一个对象中的一个线程
    this.notifyAll()通知并唤醒同一个对象中的所有线程
    注(遇到的问题):若生产消费者模型中生产者和消费者都只有一个线程的话只用this.notify()就可以了 若有多个线程必须用this.notifyAll() 
    因为this.notify()只通知唤醒一个线程 若只有一个生产者线程在跑 通知唤醒到了另一个生产者线程 导致所有线程等待 造成死锁
    
    休眠判断用while不能用if
    因为notify可能假唤醒通知 用while保证wait休眠条件
    public class Juc3 {
        public static void main(String[] args){
         Data data = new Data();
         new Thread(()->{
             for (int i = 0; i < 10; i++) {
                 try {
                     data.increment();
                 }catch (Exception e){
                     e.printStackTrace();
                 }
             }
         },"A").start();
    
            new Thread(()->{
                for (int i = 0; i < 10; i++) {
                    try {
                        data.decrement();
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }
            },"B").start();
    
            new Thread(()->{
                for (int i = 0; i < 10; i++) {
                    try {
                        data.increment();
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }
            },"C").start();
    
            new Thread(()->{
                for (int i = 0; i < 10; i++) {
                    try {
                        data.decrement();
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }
            },"D").start();
        }
    }
    
    //类中的两个方法synchronized锁 如果new一个对象 这个对象的两个方法锁是同一个锁!!!
    //同一个对象中如increment方法this.notify();通知锁取消等待就是通知了decrement方法
    class Data{
        private int number=0;
        //+1 必须有synchronized
        //等待必须用while 不用if 防止虚假唤醒
        //生产消费者业务代码流程其实就是1.等待2.通知
        public synchronized void increment() throws InterruptedException {
            while (number!=0){
                this.wait();
            }
            number++;
            System.out.println(Thread.currentThread().getName()+"=>"+number);
            //通知其它线程我执行完了+1
            this.notifyAll();
        }
        //-1
        public synchronized void decrement() throws InterruptedException {
            while (number==0){
                this.wait();
            }
            number--;
            System.out.println(Thread.currentThread().getName()+"=>"+number);
            //通知其它线程我执行完了-1
            this.notifyAll();
        }
    
    }
    2.Lock的生产者和消费者
    synchronized
    Lock lock = new ReentrantLock();
    lock加锁lock.lock();
    lock解锁lock.unlock(); 解锁步骤必须放在try的finally中以防异常
    
    Condition condition = lock.newCondition();
    condition对象作线程等待condition.await()  线程唤醒condition.signalAll()
    //Lock的生产者和消费者
    class LockTest{
        public static void main(String[] args) {
            LockData data = new LockData();
            new Thread(()->{
                for (int i = 0; i < 10; i++) {
                    try {
                        data.increment();
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }
            },"A").start();
    
            new Thread(()->{
                for (int i = 0; i < 10; i++) {
                    try {
                        data.decrement();
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }
            },"B").start();
    
            new Thread(()->{
                for (int i = 0; i < 10; i++) {
                    try {
                        data.increment();
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }
            },"C").start();
    
            new Thread(()->{
                for (int i = 0; i < 10; i++) {
                    try {
                        data.decrement();
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }
            },"D").start();
        }
    }
    
    class LockData{
        private int number=0;
        Lock lock = new ReentrantLock();
        Condition condition = lock.newCondition();
        //+1
        public void increment()  {
            lock.lock();
            try {
                while (number!=0){
                    condition.await();
                }
                number++;
                System.out.println(Thread.currentThread().getName()+"=>"+number);
                //通知其它线程我执行完了+1
                condition.signalAll();
            }catch (Exception e){
                e.printStackTrace();
            }finally {
                lock.unlock();
            }
        }
        //-1
        public void decrement() {
            lock.lock();
            try {
                while (number==0){
                    condition.await();
                }
                number--;
                System.out.println(Thread.currentThread().getName()+"=>"+number);
                //通知其它线程我执行完了-1
                condition.signalAll();
            }catch (Exception e){
                e.printStackTrace();
            }finally {
                lock.unlock();
            }
        }
    }

    3.指定唤醒某个方法的线程

    上述2个例子是以不同形式实现的同样的代码
    因此发现一个问题 
    唤醒的是同一个对象中的随机的方法或者所有方法 没有指定特定的方法
    如A()中唤醒B()唤醒C()唤醒A()循环的话
    Condition condition = lock.newCondition();
    Condition condition1 = lock.newCondition();
    可以新增多个condition对象
    condition1.await()或condition1.signal()让特定的condition对象休眠/唤醒
    class LockTest1{
        public static void main(String[] args) {
            LockData1 data = new LockData1();
            new Thread(()->{
                for (int i = 0; i < 10; i++) {
                    try {
                        data.A();
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }
            }).start();
    
            new Thread(()->{
                for (int i = 0; i < 10; i++) {
                    try {
                        data.B();
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }
            }).start();
    
            new Thread(()->{
                for (int i = 0; i < 10; i++) {
                    try {
                        data.C();
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }
            }).start();
        }
    }
    
    class LockData1{
        private int num=1;
        Lock lock = new ReentrantLock();
        Condition condition1 = lock.newCondition();
        Condition condition2 = lock.newCondition();
        Condition condition3 = lock.newCondition();
        //A 1
        public void A()  {
            lock.lock();
            try {
                while (num!=1){
                    condition1.await();
                }
                System.out.println(Thread.currentThread().getName()+"=>"+num);
                num=2;
                condition2.signalAll();
            }catch (Exception e){
                e.printStackTrace();
            }finally {
                lock.unlock();
            }
        }
        //B 2
        public void B() {
            lock.lock();
            try {
                while (num!=2){
                    condition2.await();
                }
                System.out.println(Thread.currentThread().getName()+"=>"+num);
                num=3;
                condition3.signalAll();
            }catch (Exception e){
                e.printStackTrace();
            }finally {
                lock.unlock();
            }
        }
        //C 3
        public void C() {
            lock.lock();
            try {
                while (num!=3){
                    condition3.await();
                }
                System.out.println(Thread.currentThread().getName()+"=>"+num);
                num=1;
                condition1.signalAll();
            }catch (Exception e){
                e.printStackTrace();
            }finally {
                lock.unlock();
            }
        }
    }
  • 相关阅读:
    5860. 从双倍数组中还原原数组
    5847. 找到所有的农场组
    5846. 找到数组的中间位置
    442. 数组中重复的数据
    1987. 不同的好子序列数目
    1986. 完成任务的最少工作时间段
    1985. 找出数组中的第 K 大整数
    1984. 学生分数的最小差值
    学习内容整合
    spring-DI和spring-mybatis整合
  • 原文地址:https://www.cnblogs.com/hbhb/p/14337281.html
Copyright © 2020-2023  润新知