问题描述
我有一个简单的多线程算法,旨在在后台线程中加载一系列文件,并且让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?
推荐答案
您的加载器线程正在循环运行,立即在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()不唤醒等待的线程?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!