Java多线程通信Wait和Notify,替代Suspend和Resume

Wait和Notify作用

wait

Causes the current thread to wait until another thread invokes the notify() method or the notifyAll() method for this object
The current thread must own this object’s monitor. The thread releases ownership of this monitor and waits until another thread notifies threads waiting on this object’s monitor to wake up either through a call to the notify method or the notifyAll method. The thread then waits until it can re-obtain ownership of the monitor and resumes execution.

  • 当前线程处于等待状态,等待其他线程notify。
  • 线程使用wait,必须得使用锁,而且这个锁必须是这个对象,使用后,会释放这个锁,被唤醒后,会重新获取这个锁。

示例

 synchronized (obj) {
    
    
         while (<condition does not hold>)
             obj.wait();
         ... // Perform action appropriate to condition
     }
 

notity

Wakes up a single thread that is waiting on this object’s monitor. If any threads are waiting on this object, one of them is chosen to be awakened. The choice is arbitrary and occurs at the discretion of the implementation. A thread waits on an object’s monitor by calling one of the wait methods.

The awakened thread will not be able to proceed until the current thread relinquishes the lock on this object. The awakened thread will compete in the usual manner with any other threads that might be actively competing to synchronize on this object; for example, the awakened thread enjoys no reliable privilege or disadvantage in being the next thread to lock this object.

  • 唤醒一个被wait的线程,如果有多个线程wait也只能被唤醒一个,如果需要全部唤醒,则使用notifyAll()。
  • 被唤醒的线程不能马上执行,需要等待当前线程释放锁之后,才能执行。

示例

 public void testNotify() {
    
    

        Thread thread1 = new Thread(() -> {
    
    

            synchronized (this) {
    
    
                try {
    
    
                    this.wait();
                    System.out.println("thread 1 awake");
                } catch (InterruptedException e) {
    
    
                    e.printStackTrace();
                }
            }
        });
        thread1.start();

        Thread thread2 = new Thread(() -> {
    
    
            synchronized (this) {
    
    
                try {
    
    
                    this.wait();
                    System.out.println("thread 2 awake");
                } catch (InterruptedException e) {
    
    
                    e.printStackTrace();
                }
            }
        });
        thread2.start();

        Thread thread3 = new Thread(() -> {
    
    
            synchronized (this) {
    
    
                try {
    
    
                    this.wait();
                    System.out.println("thread 3 awake");
                } catch (InterruptedException e) {
    
    
                    e.printStackTrace();
                }
            }
        });
        thread3.start();

        try {
    
    
            Thread.sleep(2000);
            synchronized (this) {
    
    
                this.notify();
                this.notify();
                System.out.println("已经调用唤醒方法,证明被唤醒的线程只有等待当前线程获取到锁之后才能进行");
                Thread.sleep(3000);
//                this.notifyAll();
            }
        } catch (InterruptedException e) {
    
    
            e.printStackTrace();
        }

    }

为什么可以替换suspend和resume

  • 线程在有所锁的情况下suspend后不会释放锁,而wait会释放锁。所以wait不容易导致死锁。

代码示例

一个是消息发送者,一个是消息接受着,当消息发送者有消息了,马上通知接受者接受消息。

 public void testWaitAndNotify() {
    
    

        Thread consumer = new Thread(() -> {
    
    

            while (true) {
    
    
                synchronized (this) {
    
    
                    while (message == null) {
    
    
                        System.out.println("等待接受消息");
                        try {
    
    
                            this.wait();
                        } catch (InterruptedException e) {
    
    
                            e.printStackTrace();
                        }
                    }
                    System.out.println("接受消息 => " + message);
                    message = null;
                }
            }
        });

        consumer.start();

        Thread producer = new Thread(() -> {
    
    
            while (true) {
    
    
                try {
    
    
                    Thread.sleep(3000);
                    message = "Hello , this is " + i++;

                } catch (InterruptedException e) {
    
    
                    e.printStackTrace();
                }
                synchronized (this) {
    
    
                    this.notifyAll();
                }

            }
        });

        producer.start();
    }

猜你喜欢

转载自blog.csdn.net/qq_36325121/article/details/108796271