zoukankan      html  css  js  c++  java
  • Java线程和多线程(二)——对象中的wait,notify以及notifyAll方法

    Java对象中的wait,notify以及notifyAll方法

    在Java的Object类中包含了3个final的方法,这三个方法允许线程来交流资源是否被锁定。这三个方法就是wait(),notify()以及notifyAll().

    在对象上调用这三个方法的线程需要包含一个对象监视器(锁),否则就会抛出java.lang.IllegalMonitorStateException异常。

    wait方法

    对象的wait方法有三个,一个是令对象等待任何线程来调用notify或者notifyAll方法来令该对象在当前线程唤醒。另外两个将当前线程置于等待状态,等到特定的时间来唤醒。

    • wait()
    • wait(long millis)
    • wait(long millis, int nanos)

    notify方法

    notify方法仅仅唤醒一个线程,令线程开始执行。所以,如果有多个线程等待一个对象的时候,这个方法只能唤醒一个线程。而唤醒的线程的选择是依赖于操作系统对于线程的管理的。

    notifyAll方法

    notifyAll方法会唤醒所有等待改对象的线程,尽管哪一个线程会优先执行时取决于操作系统的线程调度的。

    以上的三个方法都可以用来实现生产者消费者问题
    其中,消费者线程会等待队列中的对象而生产者将对象放入队列并唤醒所有等待的线程。

    下面的例子将解释多线程如何在同一个对象上使用waitnotify以及notifyAll方法。


    Message

    参考代码,Message类就是我们操作的waitnotify以及notifyAll方法的对象:

    package com.sapphire.concurrency;
    
    public class Message {
        private String msg;
    
        public Message(String str){
            this.msg=str;
        }
    
        public String getMsg() {
            return msg;
        }
    
        public void setMsg(String str) {
            this.msg=str;
        }
    
    }

    Waiter

    Waiter类的对象会等待其他线程调用notify方法来完成其执行:

    package com.sapphire.concurrency;
    
    public class Waiter implements Runnable{
    
        private Message msg;
    
        public Waiter(Message m){
            this.msg=m;
        }
    
        @Override
        public void run() {
            String name = Thread.currentThread().getName();
            synchronized (msg) {
                try{
                    System.out.println(name+" waiting to get notified at time:"+System.currentTimeMillis());
                    msg.wait();
                }catch(InterruptedException e){
                    e.printStackTrace();
                }
                System.out.println(name+" waiter thread got notified at time:"+System.currentTimeMillis());
                //process the message now
                System.out.println(name+" processed: "+msg.getMsg());
            }
        }
    }

    Notifier

    Notifier类是处理Message对象,然后调用notify方法来唤醒等待Message对象的线程的:

    package com.sapphire.concurrency;
    
    public class Notifier implements Runnable {
    
        private Message msg;
    
        public Notifier(Message msg) {
            this.msg = msg;
        }
    
        @Override
        public void run() {
            String name = Thread.currentThread().getName();
            System.out.println(name+" started");
            try {
                Thread.sleep(1000);
                synchronized (msg) {
                    msg.setMsg(name+" Notifier work done");
                    msg.notify();
                    // msg.notifyAll();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    测试代码

    package com.sapphire.concurrency;
    
    public class WaitNotifyTest {
    
        public static void main(String[] args) {
            Message msg = new Message("process it");
            Waiter waiter = new Waiter(msg);
            new Thread(waiter,"waiter").start();
    
            Waiter waiter1 = new Waiter(msg);
            new Thread(waiter1, "waiter1").start();
    
            Notifier notifier = new Notifier(msg);
            new Thread(notifier, "notifier").start();
            System.out.println("All the threads are started");
        }
    }

    当我们执行上面的程序时,我们会看到如下的输出,但是程序不会结束,因为有两个线程在等待Message对象,而我们调用的notify方法仅仅唤醒了其中的一个线程,另一个线程仍然处于等待状态,等待被唤醒。

    waiter waiting to get notified at time:1356318734009
    waiter1 waiting to get notified at time:1356318734010
    All the threads are started
    notifier started
    waiter waiter thread got notified at time:1356318735011
    waiter processed: notifier Notifier work done

    如果我们调整前面的代码,在Notifier类中调用notifyAll而不是调用notify方法的话,将会有如下输出:

    waiter waiting to get notified at time:1356318917118
    waiter1 waiting to get notified at time:1356318917118
    All the threads are started
    notifier started
    waiter1 waiter thread got notified at time:1356318918120
    waiter1 processed: notifier Notifier work done
    waiter waiter thread got notified at time:1356318918120
    waiter processed: notifier Notifier work done

    这是因为notifyAll()方法唤醒了所有的Waiter线程,所以程序完成了全部执行。

  • 相关阅读:
    Struts2项目问题及解决方式
    CSS样式编写案例
    第二个项目总结
    CSS布局中的问题解决方式
    CSS3中的Flexbox弹性布局(二)
    CSS3中的Flexbox弹性布局(一)
    python----递归函数
    python----函数进阶
    python----函数
    python----装饰器
  • 原文地址:https://www.cnblogs.com/qitian1/p/6461548.html
Copyright © 2011-2022 走看看