zoukankan      html  css  js  c++  java
  • 生产者与消费者---demo2---boke

    假设有这样一种情况,有一个桌子,桌子上面有一个盘子,盘子里只能放一颗鸡蛋,A专门往盘子里放鸡蛋,如果盘子里有鸡蛋,则一直等到盘子里没鸡蛋,B专门从盘子里拿鸡蛋,如果盘子里没鸡蛋,则等待直到盘子里有鸡蛋。其实盘子就是一个互斥区,每次往盘子放鸡蛋应该都是互斥的,A的等待其实就是主动放弃锁,B 等待时还要提醒A放鸡蛋。
    如何让线程主动释放锁
    很简单,调用锁的wait()方法就好。wait方法是从Object来的,所以任意对象都有这个方法。

    import java.util.ArrayList;   
    import java.util.List;   
      
    public class Plate {   
      
        List<Object> eggs = new ArrayList<Object>();   
      
        public synchronized Object getEgg() {   
            while(eggs.size() == 0) {   
                try {   
                    wait();   
                } catch (InterruptedException e) {   
                }   
            }   
      
            Object egg = eggs.get(0);   
            eggs.clear();// 清空盘子   
            notify();// 唤醒阻塞队列的某线程到就绪队列   
            System.out.println("拿到鸡蛋");   
            return egg;   
        }   
      
        public synchronized void putEgg(Object egg) {   
            while(eggs.size() > 0) {   
                try {   
                    wait();   
                } catch (InterruptedException e) {   
                }   
            }   
            eggs.add(egg);// 往盘子里放鸡蛋   
            notify();// 唤醒阻塞队列的某线程到就绪队列   
            System.out.println("放入鸡蛋");   
        }   
           
        static class AddThread extends Thread{   
            private Plate plate;   
            private Object egg=new Object();   
            public AddThread(Plate plate){   
                this.plate=plate;   
            }   
               
            public void run(){   
                for(int i=0;i<5;i++){   
                    plate.putEgg(egg);   
                }   
            }   
        }   
           
        static class GetThread extends Thread{   
            private Plate plate;   
            public GetThread(Plate plate){   
                this.plate=plate;   
            }   
               
            public void run(){   
                for(int i=0;i<5;i++){   
                    plate.getEgg();   
                }   
            }   
        }   
           
        public static void main(String args[]){   
            try {   
                Plate plate=new Plate();   
                Thread add=new Thread(new AddThread(plate));   
                Thread get=new Thread(new GetThread(plate));   
                add.start();   
                get.start();   
                add.join();   
                get.join();   
            } catch (InterruptedException e) {   
                e.printStackTrace();   
            }   
            System.out.println("测试结束");   
        }   
    }  
    import java.util.ArrayList;
    import java.util.List;
     
    public class Plate {
     
        List<Object> eggs = new ArrayList<Object>();
     
        public synchronized Object getEgg() {
            while(eggs.size() == 0) {
                try {
                    wait();
                } catch (InterruptedException e) {
                }
            }
     
            Object egg = eggs.get(0);
            eggs.clear();// 清空盘子
            notify();// 唤醒阻塞队列的某线程到就绪队列
            System.out.println("拿到鸡蛋");
            return egg;
        }
     
        public synchronized void putEgg(Object egg) {
            while(eggs.size() > 0) {
                try {
                    wait();
                } catch (InterruptedException e) {
                }
            }
            eggs.add(egg);// 往盘子里放鸡蛋
            notify();// 唤醒阻塞队列的某线程到就绪队列
            System.out.println("放入鸡蛋");
        }
       
        static class AddThread extends Thread{
            private Plate plate;
            private Object egg=new Object();
            public AddThread(Plate plate){
                this.plate=plate;
            }
           
            public void run(){
                for(int i=0;i<5;i++){
                    plate.putEgg(egg);
                }
            }
        }
       
        static class GetThread extends Thread{
            private Plate plate;
            public GetThread(Plate plate){
                this.plate=plate;
            }
           
            public void run(){
                for(int i=0;i<5;i++){
                    plate.getEgg();
                }
            }
        }
       
        public static void main(String args[]){
            try {
                Plate plate=new Plate();
                Thread add=new Thread(new AddThread(plate));
                Thread get=new Thread(new GetThread(plate));
                add.start();
                get.start();
                add.join();
                get.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("测试结束");
        }
    }
    

      

    执行结果:

    Html代码  

    1. 放入鸡蛋   
    2. 拿到鸡蛋   
    3. 放入鸡蛋   
    4. 拿到鸡蛋   
    5. 放入鸡蛋   
    6. 拿到鸡蛋   
    7. 放入鸡蛋   
    8. 拿到鸡蛋   
    9. 放入鸡蛋   
    10. 拿到鸡蛋   
    11. 测试结束

    声明一个Plate对象为plate,被线程A和线程B共享,A专门放鸡蛋,B专门拿鸡蛋。假设
    1 开始,A调用plate.putEgg方法,此时eggs.size()为0,因此顺利将鸡蛋放到盘子,还执行了notify()方法,唤醒锁的阻塞队列的线程,此时阻塞队列还没有线程。
    2 又有一个A线程对象调用plate.putEgg方法,此时eggs.size()不为0,调用wait()方法,自己进入了锁对象的阻塞队列。
    3 此时,来了一个B线程对象,调用plate.getEgg方法,eggs.size()不为0,顺利的拿到了一个鸡蛋,还执行了notify()方法,唤醒锁的阻塞队列的线程,此时阻塞队列有一个A线程对象,唤醒后,它进入到就绪队列,就绪队列也就它一个,因此马上得到锁,开始往盘子里放鸡蛋,此时盘子是空的,因此放鸡蛋成功。
    4 假设接着来了线程A,就重复2;假设来料线程B,就重复3。 
    整个过程都保证了放鸡蛋,拿鸡蛋,放鸡蛋,拿鸡蛋。

  • 相关阅读:
    Docker安装
    MVC-HtmlHelper简单总结
    D3.js
    分布式事务seata
    彻底搞懂JAVA路径问题
    idea 代码生成
    自动生成 serialVersionUID 的设置
    狂神说SSM框架系列连载
    缓存穿透、缓存击穿、缓存雪崩区别和解决方案
    多线程
  • 原文地址:https://www.cnblogs.com/ipetergo/p/6268902.html
Copyright © 2011-2022 走看看