3

我有这门课:

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();
    }

    }

}
4

2 回答 2

2

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

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

在 Java 教程中有一个使用 wait 和 notifyAll 的生产者-消费者示例。

于 2012-07-08T15:35:48.660 回答
1

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

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

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

于 2012-07-08T15:06:26.703 回答