美文网首页
等待/通知机制

等待/通知机制

作者: caster | 来源:发表于2021-03-15 16:29 被阅读0次

    具体流程:一个线程(生产者)修改(nofity)一个对象,另一个线程(消费者)感知到变化(wait中...)开始进行操作。
    作用:Java的等待/通知机制使消费者不需要循环一直监控对象是否变化,节约资源。
    实现原理:使用某个对象的锁来实现,Java任意对象都具有此机制,因为表中五个方法定义在Object类上。

    方法 说明
    notify() 线程调用了某对象的notify(),并释放此对象的锁后,等待线程(调用过此对象的wait()方法)有机会(如果获取到了该对象的锁)从wait()中返回。
    notifyAll() notifyAll()将等待队列中的全部线程移动到同步队列,被移动的线程状态由WAITING变为BLOCKED。
    wait() 线程内调用了某对象的wait()后会转入waiting状态,并将此线程放置到这个对象的等待队列。
    wait(long) 设置等待时间,超时则跳过等待继续执行。
    wait(long,int) 细粒度控制超时时间。

    锁和对象的关系:
    每个java对象头中都有锁状态位标记。java中在使用synchronize同步的时候,肯定是涉及到某个对象的锁。因此,在考虑同步的时候,首先要想到是同步的是哪个对象的锁。
    在java字节码上,获取了某个对象的锁之后,进入时会调用monitorenter指令,在退出时会调用monitorexit指令。可见,java object monitor是对java对象的锁的一种抽象。它和java对象是一对一的关系的。
    在java中,通过java object monitor使得锁是和其保护的对象一一对应的。
    只有拥有了该对象的锁,才可以调用以上5个方法,所以上述5个方法需要在synchronized代码块中使用,代码例例如下:

    import java.util.HashMap;
    import java.util.concurrent.ConcurrentHashMap;
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    
    public class Currrent {
        //用于操作的对象 monitor 锁
        public static Object object = new Object();
        public static void main(String[] args) throws InterruptedException {
            Wait thread1 = new Wait("wait1");
            Wait thread2 = new Wait("wait2");
            Wait thread3 = new Wait("wait3");
            Notify notify = new Notify("notify");
    
            //三个线程开始进入wait()
            thread1.start();
            thread2.start();
            thread3.start();
    
            Thread.sleep(1000);
    
            //唤醒线程进行notify()
            notify.start();
        }
    
        static class Wait extends Thread{
            private  String name;
            public Wait(String name) {
                this.name=name;
            }
            @Override
            public void run() {
                synchronized (object) {
                    try {
                        System.out.println("线程"+this.name+"进入");
                        //当前线程进入等待队列
                        object.wait(10000);
                        System.out.println("线程"+this.name+"结束wait");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("线程"+this.name+"完成");
                }
            }
        }
    
        static class Notify extends Thread{
            private  String name;
            public Notify(String name) {
                this.name=name;
            }
            @Override
            public void run() {
                synchronized (object) {
                    //所有在对象object等待队列中的线程进入阻塞度列
                    object.notify();
                    System.out.println("线程"+this.name+"调用了object.notify()");
                    System.out.println("线程"+this.name+"释放了锁");
                    //此线程释放了object对象的锁,等待队列中的某个线程将会获取并继续执行wait()方法之后的代码
                }
                try {
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("线程"+this.name+"锁外内容");
            }
        }
    }
    
    

    相关文章

      网友评论

          本文标题:等待/通知机制

          本文链接:https://www.haomeiwen.com/subject/nvikcltx.html