文档章节

synchronized&Object类的wait/notify/notifyAll(生产者消费者场景)

o
 osc_1ee7cxmx
发布于 2018/08/06 20:46
字数 957
阅读 0
收藏 0

Java中的每一个对象都有一个监视器

 

Object类的wait和notify、notifyAll方法必须在synchronized块中调用

调用一个对象的notify、notifyAll方法时,当前线程必须持有该对象的监视器monitor,否则抛出IllegalMonitorStateException

如果在synchronized块中调用另一个对象的notify、notifyAll方法,由于持有的对象的监视器不同,抛出IllegalMonitorStateException


(1)synchronized块

       synchronized(lock){

  }

  synchronized块中的方法,获得了lock实例的monitor

(2)实例synchronized方法

  public synchronized void run() {

  }

  获得了this对象的monitor

 

(3)静态synchronized方法

  public static synchronized void run() {

  }

  获得了当前类的所有对象的monitor

 

 


 

(1)wait()

一个持有当前对象的monitor的线程调用了当前对象的空参的wait方法,使得当前线程进入WARTING状态,释放锁

必须等待另一个持有当前对象的monitor的线程调用当前对象的notify或者notifyAll方法将该线程唤醒

 

(2)wait(long)

 norify

notifyAll

等待时间到

interrupt

(3)wait(long,int)

  

  wait方法必须总是存在于循环中

  

 

 

生产者、消费者场景

 

/**
 * @author DuanJiaPing
 * @date 2018/6/11 9:08
 *
 * 等待喚醒機制
 *
 *
 * Object類的方法
 * wait()
 * notify()
 * notifyAll()
 *
 * 生產者和消費者案例
 * 生產者生產的產品給店員,消費者從店員那獲取產品
 *
 * 生产者线程:创建和添加数据的线程
 * 消费者线程:删除和销毁数据的线程
 *
 * 生产者消费者案例不使用等待唤醒机制
 * 会产生以下问题
 * 数据丢失:生产者线程过快,另一面接受不到
 * 数据重复:消费者线程过快
 *
 *
 * 问题:程序结束不了
 * wait():等在方法调用处,并释放锁,当被notify或notifyAll方法唤醒之后,在等待的位置处继续执行
 * 线程被唤醒之后,被唤醒的线程和唤醒线程的线程同时抢锁
 * 解决:把notifyAll方法移到else之外
 *
 * 虚假唤醒问题:
 * 当前库存超过了最大库存或者小于0的情况
 * 解决:
 * Java API
 * wait()方法提示:应当将wait方法总是放在循环中
 *
 */
public class TestProductorAndConsumer {


    public static void main(String[] args){
        Clerk clerk = new Clerk();
        Productor productor = new Productor(clerk);
        Consumer consumer = new Consumer(clerk);

        new Thread(productor,"生产者A").start();
        new Thread(productor,"生产者B").start();
        new Thread(consumer,"消费者1").start();
        new Thread(consumer,"消费者2").start();

    }


}

/*
* 店员类
* 店员进货、售货,只有一个店员
* */

class Clerk{

    /*库存*/

    private int product = 0;

    /*
    * 此时,进货和售货的两个方法都操作共享数据product(库存)
    * 因此,这两个方法都存在线程安全问题
    * 解决:同步方法,同步代码块
    *
    * */

    /*
    * 进货
    * */

    public synchronized void get(){

        while (product >= 5) {
            System.out.println("库存已满");
            try{
                //将wait放在while循环中,当多个线程在此处等待,并被notifyAll唤醒之后,会再循环判断一次product的值
                wait();
            }catch(Exception e){

            }
        }
//        if(product >= 1) {
//            System.out.println("库存已满");
//            try{
//                wait();//当两个线程同时wait在此处,notifyAll之后,两个线程都从这块开始执行,都执行下面的sysout,都将product(库存)加一
//            }catch(Exception e){
//
//            }
//        }

        /*else{
            System.out.println(Thread.currentThread().getName()+"--进货--当前库存--"+ ++product);

            notifyAll();
        }*/

        System.out.println(Thread.currentThread().getName()+"--进货--当前库存--"+ ++product);

        notifyAll();

    }

    /*
    * 售货
    * */

    public synchronized void sale(){
        while(product <= 0){
            System.out.println("库存不足");
            try{
                wait();
            }catch(Exception e){

            }
        }

        System.out.println(Thread.currentThread().getName()+"--售货--当前库存--"+ --product);

        notifyAll();
    }
}


/*生产者类,生产者生产产品提供给店员
* 生产者有多个
* 多线程
* */

class Productor implements Runnable{
    private Clerk clerk;

    public Productor(Clerk clerk) {
        this.clerk = clerk;
    }

    @Override
    public void run() {
        //不断生产10个产品,提供给店员
        try{
            Thread.sleep(200);
        }catch (Exception e){

        }

        for(int i=1;i<=10;i++){
            clerk.get();
        }
    }
}


/*消费者类
* 消费者从店员处购买产品
* 多个消费者
* 多线程*/

class Consumer implements Runnable{
    private Clerk clerk;

    public Consumer(Clerk clerk) {
        this.clerk = clerk;
    }

    @Override
    public void run() {
        for(int i=1;i<=10;i++){
            clerk.sale();
        }

    }
}

 



o
粉丝 0
博文 500
码字总数 0
作品 0
私信 提问
加载中
请先登录后再评论。

暂无文章

Openstack 从入门到放弃 - Ussuri release -0701

使用vmware 虚拟机环境搭建测试 OS: CentOS 8 此示例体系结构与最小生产体系结构不同,如下所示: 网络代理驻留在控制器节点上,而不是一个或多个专用网络节点上。 自助服务网络的覆盖(隧道...

osc_icwhzig7
10分钟前
5
0
如何用Nearby Service开发针对附近人群的精准广告推送功能

  当你想找一家餐厅吃饭,却不知道去哪家,这时候手机跳出一条通知,为你自动推送附近优质餐厅的信息,你会点击查看吗?当你还在店内纠结于是否买下一双球鞋时,手机应用给了你发放了老顾客...

osc_7dwwmolq
11分钟前
4
0
vue全局防抖和节流

函数防抖 防抖分为两种: 一种是立即执行:频繁触发事件,第一次触发时执行函数,后面触发不会执行,停止触发,间隔一定时间之后再触发事件,函数才会再次执行 另一种是后执行:频繁...

我心中有猛狗
12分钟前
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部