【问题标题】:About wait and notifyAll关于wait和notifyAll
【发布时间】:2012-07-08 04:49:26
【问题描述】:

我有这门课:

public class MyThread implements Runnable {

    private static boolean canAccess = true;
    private Thread t;

    public FirstThread(String name) {
    t = new Thread(this);
    t.setName(name);
    }

    public void start() {
        t.start();
    }

    private synchronized void accessed(String name) throws InterruptedException {
    if (canAccess) {
        canAccess = false;
        System.out.println("Accessed " + name);
        try {
        Thread.sleep(5000);
        } catch (Exception e) {
        }
        canAccess = true;
        System.out.println("NOTIFY: " + name);
        notifyAll();
    }
    System.out.println("WAIT: " + name);
    wait();

    }

    @Override
    public void run() {
    while (true) {
        try {
        accessed(Thread.currentThread().getName());
        } catch (InterruptedException e) {
        e.printStackTrace();
        }
    }
    }
}

这是我的输出:

Accessed 1
WAIT: 3
WAIT: 5
WAIT: 7
WAIT: 9
WAIT: 0
WAIT: 2
WAIT: 4
WAIT: 6
WAIT: 8
NOTIFY: 1
WAIT: 1

我的应用程序冻结(死锁状态)。 似乎 notifyAll 方法不起作用。我的错误在哪里?

我的主要课程。

public class Main {

    public static void main(String[] args) {
    MyThread [] threads = new MyThread[10];
    for(int i=0;i<threads.length;i++) {
        threads[i] = new MyThread(""+i);
        threads[i].start();
    }

    }

}

【问题讨论】:

  • 在构造函数中启动一个线程很少是一个好主意。不确定这是否是问题所在。例如:stackoverflow.com/questions/5623285/…
  • 你是对的,但我已经更改了我的代码,但仍然无法正常工作。
  • 我看不出重点是将canAccess首先设置为false,然后在使用此变量的唯一synchronized块中设置true
  • 我是否更正了您创建 10 个 MyThread 类实例,然后调用每个方法的 start()。您能否提供一段代码,这将显示更好的画面。我猜每个线程都在等待自己的实例,没有人唤醒它们。
  • @MarkoTopolnik 对不起,我不明白。如果我设置 canAccess = true 并调用 notifyAll,理论上我应该有“线程竞赛”或者我错过了什么?

标签: java multithreading wait notify


【解决方案1】:

每个线程都在自己的实例上等待,这就是为什么它们都卡在一个地方的原因。

如果你有一个private static Object LOCK = new Object(); 并调用 LOCK.wait();和 LOCK.notify();这可能是另一个故事。

我也怀疑 access() 方法的同步修饰符。它只是在所描述的情况下没有用。我最好修改同步块中的“canAccess”变量。

【讨论】:

    【解决方案2】:

    wait 表示线程释放锁并进入休眠状态,直到另一个线程通知它。 notifyAll 表示该线程告诉所有其他等待当前同步块中正在使用的锁的线程唤醒并再次尝试获取锁。您的代码示例没有任何情况下多个线程试图获取相同的锁,因此在此处使用 wait 和 notifyAll 没有任何意义。一旦调用wait,就没有什么可以唤醒线程了。

    wait 和 notify 的一种典型用法:您可能有许多生产者将内容放入队列中,而消费者线程则将内容从队列中取出。队列有一个消费者调用的 take 方法,如果队列为空,则调用 wait 并且消费者阻塞。队列有一个 put 方法,当有东西进入队列时调用 notifyAll 以便任何等待的消费者线程唤醒。

    Java 教程中有a producer-consumer example of using wait and notifyAll

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-10-11
      • 1970-01-01
      • 2013-02-23
      • 1970-01-01
      • 1970-01-01
      • 2018-01-20
      • 2011-09-11
      相关资源
      最近更新 更多