生产消费者模式
情景:
有个类,包含增加,减少两个方法。当数量为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
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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(); }
这是因为number++,对象都变了。改成用AtomicInteger。就不会报错了
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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(); } } } }
方法3:synchronized 普通方法,用 this.wait()
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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(); } } }
方法4:synchronized 普通方法,用 ShareSource5.class.wait();
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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(); } } }