gpt4 book ai didi

java - 为什么我不能使用notifyAll()来唤醒正在等待的线程?

转载 作者:行者123 更新时间:2023-12-01 11:32:25 25 4
gpt4 key购买 nike

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

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 部分,通过鼠标单击方法打开文件选择器窗口以让用户选择文件。代码

        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()唤醒第一个线程,以便它可以发送图像。

最佳答案

正如 @MadProgrammer 提到的,您没有在同一个锁上同步。好吧,不知道还能如何描述它。这是一把锁。要在 Java 中锁定并等待,您需要选择一个对象来表示“锁”。

如果两个线程在两个不同的对象上同步,就像第一个线程说“我正在泵#1中泵气,如果你需要使用它,请排队”,然后第二个线程说“嘿,让我知道您何时完成#2"(当泵 2 停止服务时)。

如果您希望第二个驱动程序等待第一个驱动程序完成泵送,那么他需要声明对泵 #1 的兴趣,即由其他人持有的同一泵。同样,如果您希望两个线程成功执行等待和通知,它们需要引用同一个对象。

为什么在您的情况下这可能会显得令人困惑,因为您没有指定要锁定的显式对象。您将方法声明为synchronized,它隐式使用该方法正在执行的对象的实例作为锁资源。

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 实例,因此它们不会互相阻塞,因为它们具有完全独立的锁。

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.
}

看看输出有何不同。第二个线程必须排队等待第一个线程。

关于java - 为什么我不能使用notifyAll()来唤醒正在等待的线程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30292416/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com