Search code examples
javamultithreadingswingswingworker

How to wake up waiting SwingWorker?


I have a SwingWorker that is running in the background. After it works on some stuff. It will wait. When the user push a button, the MyListener will be invoked and wake up the worker to continue do some stuff. It is not working like I thought it would. It throws an exception at the bottom. Please tell me what I did wrong.

 MyWorker worker = new MyWorker();    

 class MyListener implements ActionListener {

    @Override
    public void actionPerformed (ActionEvent e) {

         //DO some stuff and wake up worker  
         worker.notify ();           
    }
}

class MyWorker extends SwingWorker {

    boolean _work = true;

    @Override
    protected Object doInBackground() throws Exception {
        System.out.println ("in myWorker");
        while (_work == true) {

          //DO some stuff here
            wait();        
        }
        return null;
    }
}

The exception:

Exception in thread "AWT-EventQueue-0" java.lang.IllegalMonitorStateException
    at java.lang.Object.notify(Native Method)
    at worker.Worker$2.actionPerformed(Worker.java:54)
    at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2018)
    at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2341)
    at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402)
    at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259)
    at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:252)
    at java.awt.Component.processMouseEvent(Component.java:6505)
    at javax.swing.JComponent.processMouseEvent(JComponent.java:3321)
    at java.awt.Component.processEvent(Component.java:6270)
    at java.awt.Container.processEvent(Container.java:2229)
    at java.awt.Component.dispatchEventImpl(Component.java:4861)
    at java.awt.Container.dispatchEventImpl(Container.java:2287)
    at java.awt.Component.dispatchEvent(Component.java:4687)
    at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4832)
    at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4492)
    at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4422)
    at java.awt.Container.dispatchEventImpl(Container.java:2273)
    at java.awt.Window.dispatchEventImpl(Window.java:2713)
    at java.awt.Component.dispatchEvent(Component.java:4687)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:707)
    at java.awt.EventQueue.access$000(EventQueue.java:101)
    at java.awt.EventQueue$3.run(EventQueue.java:666)
    at java.awt.EventQueue$3.run(EventQueue.java:664)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:87)
    at java.awt.EventQueue$4.run(EventQueue.java:680)
    at java.awt.EventQueue$4.run(EventQueue.java:678)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:677)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:211)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:128)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:117)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:113)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:105)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:90)

Solution

  • You need to add a synchronized block around the notify call.

    synchronized (worker) {
        worker.notify();
    }
    

    Now, having said that, you are generally discouraged from using instance variables as monitor locks and instead use a static final lock object as (amongst other things) it decreases the potential of having the wrong instance