notifyAll () не пробуждает поток - PullRequest
1 голос
/ 03 марта 2020

Это из моей программы. Открывается окно с кнопкой. Когда я нажимаю кнопку, она должна закрыть окно и пробудить другой поток. Но это никогда не пробуждает другую нить. "возвращено в нить" внизу никогда не печатает, и я не могу понять, почему.

public class BrandingGui {
 public synchronized void replaceImage() throws IOException{
...
 JButton keepButton = new JButton("Keep");
 keepButton.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent arg0) {
                    frame.dispose();
                    synchronized(BrandingGui.class) { 
                        //BrandingGui.this.notify();
                        notifyAll();
                    }
            }          
          });

...

   try {

           synchronized(BrandingGui.class) {    
           this.wait();
         } 
catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
System.out.println("returned to thread");
}
}

1 Ответ

2 голосов
/ 03 марта 2020

Похоже, у вас все работает (из комментариев), так что это здорово, но для адресации вашего кода OP:

При использовании блокировки на уровне класса в синхронизированной необходимо использовать блокировку на уровне класса на ждать / уведомлять - и не смешивать блокировку экземпляра (это) с блокировкой на уровне класса:

public class MyClass {
    public static void main(String args[]) {

        Thread t = new Thread(new Runnable() {
            public void run() {

                synchronized (MyClass.class) {
                    MyClass.class.notifyAll();
                    System.out.println("Awake");
                }
            }
        });
        t.start();

        synchronized (MyClass.class) {
            try {            
                System.out.println("here");
                MyClass.class.wait();

            } catch (InterruptedException ie) {

            }
        }

        System.out.println("Done");
    }
}

Отпечатки:

here
Awake
Done

В вашем случае OP вы использовали блокировку на уровне класса для synchronized и использования this блокировки объекта на notifyall:

synchronized(BrandingGui.class) { 
    notifyAll();   // WRONG - this is the `this` instance lock.
}

Так что в этом случае это должно быть:

synchronized(BrandingGui.class) { 
    BrandingGui.class.notifyAll();
}
...