Java notifyAll()不工作

Java notifyAll()不工作,java,multithreading,concurrency,wait,Java,Multithreading,Concurrency,Wait,在下面的代码中,将调用notifyAll,但不会重新激活其他线程。我得到的输出是 等待通知的测试版时间:1441870698303,activeWriters:1 alpha等待得到通知的时间:1441870698303,activeWriters:1 增量随时通知:1441870698403,ActiveWriter:0 公共类服务生实现可运行{ private static int activeWriters; public Waiter(Message msg){

在下面的代码中,将调用notifyAll,但不会重新激活其他线程。我得到的输出是

等待通知的测试版时间:1441870698303,activeWriters:1

alpha等待得到通知的时间:1441870698303,activeWriters:1

增量随时通知:1441870698403,ActiveWriter:0

公共类服务生实现可运行{

    private static int activeWriters;

    public Waiter(Message msg){
    }

    @Override
    public void run() {
        beforeWrite();
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        afterWrite();
    }

    protected synchronized void beforeWrite(){
        while (activeWriters > 0 ) {
            try {
                System.out.println(Thread.currentThread().getName() +" waiting to get notified at time: "+System.currentTimeMillis()+ ", activeWriters: " + activeWriters);
                wait();
                System.out.println(Thread.currentThread().getName() +" waiting got notified at time: "+System.currentTimeMillis()+ ", activeWriters: " + activeWriters);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        ++activeWriters;
    }
    protected synchronized void afterWrite(){
        --activeWriters;
        System.out.println(Thread.currentThread().getName() +" notify all at time: "+System.currentTimeMillis() + ", activeWriters: " + activeWriters);
        notifyAll();
    }

}

public class WaitNotifyTest {

    public static void main(String[] args) {
        Message msg = new Message("process it");
        Waiter waiter1 = new Waiter(msg);
        Waiter waiter2 = new Waiter(msg);
        Waiter waiter3 = new Waiter(msg);
        new Thread(waiter1,"alpha").start();
        new Thread(waiter2, "beta").start();
        new Thread(waiter3, "delta").start();

    }

}
调用wait和notify*在指定对象上工作,这意味着notify*会唤醒在同一对象上调用wait的线程

在您的情况下,在3个未连接的不同对象上调用wait和notifyAll,因此这无法工作

您可以添加静态互斥:

private static final Object mutex = new Object();
然后在此对象上调用wait和notify*。请记住首先在互斥锁上进行同步:

synchronized (mutex) {
    ...
    mutex.wait();
    ...
}
以及:


出于两个原因,对ActiveWriter的所有访问都必须在这些同步块中。当前对ActiveWriter的访问实际上是不同步的,因为您在3个不同的对象上同步。除此之外,ActiveWriter是您的条件变量,您希望通知*其他线程它已更改。为此,请更改变量和notify*调用必须在同一个同步块中。

您的程序中存在一个主要的设计缺陷

您正在创建3个单独的服务生类实例,并希望所有实例都以同步方式访问ActiveWriter。这是不可能的,因为实例方法将获取不同的锁,但修改相同的静态变量ActiveWriter

要提供静态变量并发访问,您应该通过.synchronized静态方法访问它们。
一种方法是将beforeWrite和afterWrite方法设置为静态。

Thx作为答案。我现在看到3个线程之间确实没有链接。如果我理解正确,我的beforeWrite方法应该更改为protected void beforeWrite{synchronized mutex{而ActiveWriter>0{尝试{mutex.wait;}捕获中断异常e{e.printStackTrace;}}++activeWriters;}}}@user3637488是的,第二种方法也是如此。Thx非常有效。ps很抱歉注释中的代码格式错误:我对并发性做了一些额外的研究。我的代码中ActiveWriter的声明应该是私有静态volatile int activeWriter,因为多个线程访问此变量able?@user3637488如果总是从同步块访问共享变量,则不需要volatile。
synchronized (mutex) {
    ...
    mutex.notifyAll();
    ...
}