为什么不能使用notifyAll()唤醒等待的线程? [英] Why can't I use notifyAll() to wake up a waiting thread?

查看:504
本文介绍了为什么不能使用notifyAll()唤醒等待的线程?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个具有以下两种方法的线程类:

I have a thread class having the following two methods:

public void run()
{
    boolean running=true;
    while(running)
    {
        sendImage();
    }
}

private synchronized void sendImage()
{
        if(!imageready.getFlag())
        { 
            try
            {
                wait();
                System.out.println("woke up!");
            }
            catch(Exception e)
            {
                System.out.println("Exception raises in ImgSender while waiting");
            }

        }
        else
        {
            //send image
        }
}

我还有一个GUI部件,它带有鼠标单击方法,可以打开文件选择器窗口,让用户选择文件.代码

I also has a GUI part with a mouse click method to open the file chooser window to let user choose file. The code

        public void mouseClicked (MouseEvent event) 
        {
           chooser=new JFileChooser();

           int status=chooser.showOpenDialog(null);


           if (status == JFileChooser.APPROVE_OPTION)
           { 
               try
               {
                    prepareImage();
               }
               catch(Exception e)
               {
                   System.out.println("file not opened");
                }
            }
         }

   private synchronized void prepareImage() throws Exception
    {
           System.out.println("File chosen");
           imgFile=chooser.getSelectedFile();  
           image.setImg( ImageIO.read(imgFile) );
           imageready.setFlag(true);
           notifyAll();  
           System.out.println("noticed other threads");
    }

但是我无法使用notifyAll()唤醒第一个线程,以便它可以发送图像.

But I can't wake the first thread up using the notifyAll() so that it could send the image.

推荐答案

如@MadProgrammer所述,您没有在同一锁上进行同步.好吧,不确定是否还有其他描述它的方法.这是一把锁.要在Java中锁定并等待,请选择一个代表锁定"的对象.

As @MadProgrammer mentioned, you are not synchronizing on the same lock. A lock is, well, not sure how else to describe it. It's a lock. To lock and wait in Java, you pick an object to represent the "lock".

如果2个线程在2个不同的对象上同步,则就像第一个线程说我正在1号泵中抽气,如果需要使用它,请排队",然后第二个线程说嘿,让我知道何时使用#2"(泵2停止运行时).

If 2 threads synchronize on 2 different objects, it's like the first thread saying "I am pumping gas in pump #1, if you need to use it, get in line", then the second thread saying "Hey, let me know when you're done with #2" (when pump 2 is out of service).

如果您希望第二个驾驶员等待第一个驾驶员完成抽水,那么他需要对第一个泵(对其他人持有的相同的泵)感兴趣.同样,如果您希望2个线程成功执行等待和通知,则它们需要引用同一对象.

If you want the second driver to wait for the first driver to finish pumping, then he needs to declare interest in pump #1, the same pump that is being held by someone else. Likewise, if you want 2 threads to successfully perform a wait and notify, they need to refer to the same object.

在您的情况下,这可能会引起混淆的原因是您未指定要锁定的显式对象.您将方法声明为synchronized,它隐式地使用该方法针对其执行的对象的实例作为锁定资源.

Why this may appear confusing in your situation is that you aren't specifying explicit objects to lock on. You declared your methods as synchronized, which implicitly uses the instance of the object the method is executing against as the lock resource.

public class LockTest implements Runnable {
    public void synchronized doNothing() {
        try {
            System.out.println("Starting lock...");
            Thread.sleep(5000);
            System.out.println("Releasing lock...");
        }
        catch (InterruptedException e) {
        }
    }

    public static void main(String[] args) {
        LockTest test1 = new LockTest();
        LockTest test2 = new LockTest();
        new Thread(test1).start();
        new Thread(test2).start();
        // Notice from the output that the threads do not block each other.
    }
}

我们创建了2个LockTest实例,因此它们彼此完全独立,因此不会相互阻塞.

We created 2 instances of LockTest, so they do not block each other since they have completely independent locks.

public class LockTest implements Runnable {
    private Object thingToLockWith;

    public LockTest(Object thingToLockWith) {
        this.thingToLockWith = thingToLockWith;
    }

    public void doNothing() {
        synchronized (thingToLockWith) {
            try {
                System.out.println("Starting lock...");
                Thread.sleep(5000);
                System.out.println("Releasing lock...");
            }
            catch (InterruptedException e) {
            }
        }
    }

    public static void main(String[] args) {
        Object lock = new Object();

        LockTest test1 = new LockTest(lock);
        LockTest test2 = new LockTest(lock);
        new Thread(test1).start();
        new Thread(test2).start();
        // Notice from the output they block.
    }

查看输出如何不同.第二个线程必须排队等待第一个线程.

See how the output differs. The second thread has to wait in line for the first thread.

这篇关于为什么不能使用notifyAll()唤醒等待的线程?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆