生产者和消费者问题(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();
        }
    }
}

 

posted @ 2021-01-27 22:07  小白小白小白小白  阅读(139)  评论(0编辑  收藏  举报