问题描述
我有一个具有以下两种方法的线程类:
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()唤醒等待的线程?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!