Java 了解多线程等待和通知

Java 了解多线程等待和通知,java,multithreading,Java,Multithreading,我正在学习多线程,并试图理解如何使用对象类的wait和notify方法。我已经通过了这个链接,并编写了以下程序 侍者 public class Waiter implements Runnable { private Message m; public Waiter(Message m) { this.m = m; } public void run() { String name = Thread.currentThread()

我正在学习多线程,并试图理解如何使用对象类的wait和notify方法。我已经通过了这个链接,并编写了以下程序

侍者

public class Waiter implements Runnable {
    private Message m;
    public Waiter(Message m) {
         this.m = m;
    }
    public void run() {
        String name = Thread.currentThread().getName();
        System.out.println(t1 + " thread waiting for message");
        synchronized (m) {
            try {
                m.wait();
                System.out.println(t1 + " " + m.getText());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println(t1 + " thread waiting for message");
    }
}
通知者

public class Notifier implements Runnable {
    private Message m;
    public Notifier(Message m) {
         this.m = m;
    }
    public void run() {
        synchronized (m) {
            try {
                Thread.sleep(2000);
                m.notifyAll();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
试验

当我执行程序时,它有时正确地终止,有时无限期地等待,有时一个线程终止,另一个线程无限期地等待。谁能告诉我这里怎么了


另外,我还想知道一些等待和通知方法的实时应用示例。

当您执行等待时,最佳实践是在一个带条件的while循环中执行。可能会出现这样的情况,线程将通知,然后其他线程进入等待状态。因此线程将始终处于等待状态

修改代码:

public class Waiter implements Runnable {
    private Message m;

    public Waiter(Message m) {
        this.m = m;
    }

    public void run() {
        String name = Thread.currentThread().getName();
        System.out.println(name + " thread waiting for message");
        synchronized (m) {
            try {
                while (m.getText() == null) {
                    m.wait();
                }
                System.out.println(name + " " + m.getText());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println(name + " thread waiting for message");
    }
}

public class Notifier implements Runnable {
    private Message m;

    public Notifier(Message m) {
        this.m = m;
    }

    public void run() {
        synchronized (m) {

            m.setText("hello");
            m.notifyAll();

        }
    }
}

public class WaitNotifyTest {
    public static void main(String[] str) {
        Message m = new Message();
        new Thread(new Waiter(m), "t1").start();
        new Thread(new Waiter(m), "t2").start();
        new Thread(new Notifier(m)).start();
    }
}

我认为问题在于通知程序类的同步块中的Thread.sleep(2000)。一旦我将其移出同步块,程序就会始终正确终止。有人能告诉我这里有什么不同吗?假设
通知程序
线程首先运行,并进入
同步(m)
部分<代码>服务员
线程无法进入此分区,直到
通知程序
离开它。但在离开时,
m.notifyAll()
已执行。因此,当
water
进入该部分并执行
m.wait()
时,它将永远等待:之后没有人会通知线程。通过将
Thread.sleep(2000)
移动到分区之外,您使给定场景变得不太可能:而
Notifier
在关键分区之外休眠,当我将Thread.sleep移到synchronized块之外并且程序正确终止时,
water
很有可能首先进入该部分。或者,我按照你的建议,将Thread.sleep移回synchronized并添加了循环,程序很好地终止了。我无法理解在同步块内部和外部使用Thread.sleep有什么区别。使用Thread sleep时,它总是暂停当前线程的执行,线程睡眠不会丢失当前线程获得的任何监视器或锁。因此,wait在通知程序之后执行的可能性很高。@gati sahu-因为代码使用notifyAll()不会调用所有等待的线程。此外,张贴的代码对我来说没有阻塞。我能想到的唯一可能性是,如果通知是在线程等待()之前处理的。@gatisahu很抱歉,我不明白。我不熟悉多线程。我只有理论知识。你能详细解释一下吗?
public class Waiter implements Runnable {
    private Message m;

    public Waiter(Message m) {
        this.m = m;
    }

    public void run() {
        String name = Thread.currentThread().getName();
        System.out.println(name + " thread waiting for message");
        synchronized (m) {
            try {
                while (m.getText() == null) {
                    m.wait();
                }
                System.out.println(name + " " + m.getText());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println(name + " thread waiting for message");
    }
}

public class Notifier implements Runnable {
    private Message m;

    public Notifier(Message m) {
        this.m = m;
    }

    public void run() {
        synchronized (m) {

            m.setText("hello");
            m.notifyAll();

        }
    }
}

public class WaitNotifyTest {
    public static void main(String[] str) {
        Message m = new Message();
        new Thread(new Waiter(m), "t1").start();
        new Thread(new Waiter(m), "t2").start();
        new Thread(new Notifier(m)).start();
    }
}