为什么我的notify()不唤醒等待的线程? [英] why does my notify() not wake a waiting thread?
问题描述
我有一个简单的多线程算法,旨在在后台线程中加载一系列文件,并且让JPanel在加载完成后立即显示第一个图像.在JPanel的构造函数中,我启动加载程序,然后等待图像列表,如下所示:
I have a simple multithreaded algorithm designed to load a series of files in a background thread, and have a JPanel display the first image as soon as it is done loading. In the constructor of the JPanel, I start the loader, then wait on the list of images, as follows:
//MyPanel.java
public ArrayList<BufferedImage> images = new ArrayList<BufferedImage>();
int frame;
public MyPanel(String dir){
Thread loader = new thread (new Loader(dir, this));
loader.start();
frame = 0;
//miscellaneous stuff
synchronized(images){
while (images.isEmpty()){
images.wait();
}
}
this.setPrefferedSize(new Dimension(800,800));
}
@Override
public void paintComponent(Graphics g){
super.paintComponent(g)
g.drawImage(images.get(frame), 0, 0, 800, 800, null);
}
我的Loader线程看起来像这样:
my Loader thread looks like this:
//Loader.java
String dir;
MyPanel caller;
public Loader(String dir, MyPanel caller){
this.dir = dir;
this.caller = caller;
}
@Override
public void run(){
File dirFile = new File(dir);
File[] files = dirFile.listFiles();
Arrays.sort(files);
for (File f : files) {
try {
synchronized (caller.images) {
BufferedImage buffImage = ImageIO.read(f);
caller.images.add(buffImage);
caller.images.notifyAll();
}
} catch (IOException e) {
}
}
}
我已经验证了调用线程唤醒并在帧中显示图像之前,执行多次通过notifyAll()
(通常> 20).我还验证了images对象实际上与正在等待的对象是同一对象.我尝试添加yield()
,但这没有帮助.为什么对notifyAll()
的调用不能立即唤醒等待的线程?
I have verified that execution passes through notifyAll()
several times (usually >20) before the calling thread wakes up and displays the image in the frame. I have also verified that the images object is in fact the same object as the one being waited on. I have attempted adding a yield()
, but that did not help. why does the call to notifyAll()
not wake the waiting thread immediately?
推荐答案
我已经验证了调用线程被唤醒并在帧中显示图像之前,执行多次通过notifyAll()(通常> 20).
I have verified that execution passes through notifyAll() several times (usually >20) before the calling thread wakes up and displays the image in the frame.
您的加载器线程正在循环运行,立即在caller.images
上重新获取监视器,可能是在它放弃其时间片之前.
Your loader thread is looping, immediately reacquiring the monitor on caller.images
, probably before it gives up its timeslice.
等待的线程必须先获取监视器,然后监视器才能取得进度-之所以不能这样做,是因为加载程序再次抓住了它.
The waiting thread has to reacquire the monitor before it can make progress - which it can't do because the loader has grabbed it again.
目前尚不清楚您要在这里实现什么,但是启动一个新线程,然后在构造函数中等待 通常是一个非常糟糕的主意.哎呀,如果在加载第一个图像之前根本无法做任何事情,为什么不同步进行呢?那就是你有效地所要做的...
It's not really clear what you're trying to achieve here, but starting a new thread and then waiting within a constructor is generally a really bad idea. Heck, if you can't do anything at all until the first image has loaded, why not do that synchronously? That's what you're effectively doing anyway...
这篇关于为什么我的notify()不唤醒等待的线程?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!