生产消费者模式

情景:

有个类,包含增加,减少两个方法。当数量为0时才能增加,数量为1的时候才能减少。两个线程分别调用增加和减少方法。

主要用于熟悉方法同步和块同步。

 

方法1:synchronized 一个其他变量

class ShareSource2{

    private Integer number = 0;
    private byte[] lock = new byte[0];

    public void increase(){//我发现,如果把synchronized房子方法上,而不加synchronized (lock),会报IllegalMonitorStateException
        synchronized (lock){
            try {
                while (number!=0){
                    lock.wait();
                }
                number++;
                System.out.println(Thread.currentThread().getName()+"\t "+number);
                lock.notify();

            }catch (InterruptedException e){
                System.out.println("increase exception");
                e.printStackTrace();
            }
        }
    }


    public void decrease(){
        synchronized (lock){
            try {
                while (number!=1){
                    lock.wait();
                }
                number--;
                System.out.println(Thread.currentThread().getName()+"\t "+number);
                lock.notify();

            }catch (InterruptedException e){
                System.out.println("increase exception");
                e.printStackTrace();
            }
        }
    }

}



public static void main(String[] args) {

        ShareSource2 shareSource = new ShareSource2();

        new Thread(() -> {
            for (int i = 0; i < 5; i++) {
                shareSource.increase();
            }
        }, "AA").start();

        new Thread(() -> {
            for (int i = 0; i < 5; i++) {
                shareSource.decrease();
            }
        }, "BB").start();
    }

执行结果如下:

 

 

 方法2:synchronized 一个操作变量(*这个需要特别注意,不然会报IllegalMonitorStateException 异常)

 1)如果使用Integer

class ShareSource3{

    private Integer number = 0;
//    private AtomicInteger number = new AtomicInteger(0);

    
    public void increase(){//我发现,如果把synchronized房子方法上,而不加synchronized (lock),会报IllegalMonitorStateException

        synchronized (number){
            try {
                while (number!=0){
                    number.wait();
                }
                number++;
                System.out.println(Thread.currentThread().getName()+"\t "+number);
                number.notify();

            }catch (InterruptedException e){
                System.out.println("increase exception");
                e.printStackTrace();
            }
        }
    }


    public void decrease(){
        synchronized (number){
            try {
                while (number!=1){
                    number.wait();
                }
                number--;
                System.out.println(Thread.currentThread().getName()+"\t "+number);
                number.notify();

            }catch (InterruptedException e){
                System.out.println("increase exception");
                e.printStackTrace();
            }
        }
    }

}


public static void main(String[] args) {

        ShareSource3 shareSource = new ShareSource3();

        new Thread(() -> {
            for (int i = 0; i < 5; i++) {
                shareSource.increase();
            }
        }, "AA").start();

        new Thread(() -> {
            for (int i = 0; i < 5; i++) {
                shareSource.decrease();
            }
        }, "BB").start();
    }
View Code

 

 这是因为number++,对象都变了。改成用AtomicInteger。就不会报错了

class ShareSource3{

//    private Integer number = 0;
    private AtomicInteger number = new AtomicInteger(0);


    public void increase(){//我发现,如果把synchronized房子方法上,而不加synchronized (lock),会报IllegalMonitorStateException

        synchronized (number){
            try {
                while (number.get()!=0){
                    number.wait();
                }
                number.getAndIncrement();
                System.out.println(Thread.currentThread().getName()+"\t "+number);
                number.notify();

            }catch (InterruptedException e){
                System.out.println("increase exception");
                e.printStackTrace();
            }
        }
    }


    public void decrease(){
        synchronized (number){
            try {
                while (number.get()!=1){
                    number.wait();
                }
                number.getAndDecrement();
                System.out.println(Thread.currentThread().getName()+"\t "+number);
                number.notify();

            }catch (InterruptedException e){
                System.out.println("increase exception");
                e.printStackTrace();
            }
        }
    }

}
View Code

 

 方法3:synchronized 普通方法,用 this.wait()

class ShareSource4{

    //    private Integer number = 0;
    private AtomicInteger number = new AtomicInteger(0);
    
    public synchronized void increase(){//我发现,如果把synchronized房子方法上,而不加synchronized (lock),会报IllegalMonitorStateException

        try {
            while (number.get()!=0){
                this.wait();//如果换成 number.wait(),会报IllegalMonitorStateException
            }
            number.getAndIncrement();
            System.out.println(Thread.currentThread().getName()+"\t "+number.get());
            this.notify();

        }catch (InterruptedException e){
            System.out.println("increase exception");
            e.printStackTrace();
        }
    }


    public synchronized void decrease(){
        try {
            while (number.get()!=1){
                this.wait();
            }
            number.getAndDecrement();
            System.out.println(Thread.currentThread().getName()+"\t "+number.get());
            this.notify();

        }catch (InterruptedException e){
            System.out.println("increase exception");
            e.printStackTrace();
        }
    }

}
View Code

 

方法4:synchronized 普通方法,用 ShareSource5.class.wait();

 

class ShareSource5{

    //    private Integer number = 0;
    private static AtomicInteger number = new AtomicInteger(0);
    
    public synchronized static void increase(){//我发现,如果把synchronized房子方法上,而不加synchronized (lock),会报IllegalMonitorStateException

        try {
            while (number.get()!=0){
                ShareSource5.class.wait();//如果换成 number.wait(),会报IllegalMonitorStateException
            }
            number.getAndIncrement();
            System.out.println(Thread.currentThread().getName()+"\t "+number.get());
            ShareSource5.class.notify();

        }catch (InterruptedException e){
            System.out.println("increase exception");
            e.printStackTrace();
        }

    }


    public synchronized static void decrease(){
        try {
            while (number.get()!=1){
                ShareSource5.class.wait();
            }
            number.getAndDecrement();
            System.out.println(Thread.currentThread().getName()+"\t "+number.get());
            ShareSource5.class.notify();

        }catch (InterruptedException e){
            System.out.println("increase exception");
            e.printStackTrace();
        }
    }

}
View Code

 

posted @ 2021-09-02 16:18  Lucy151213  阅读(45)  评论(0编辑  收藏  举报