我想做一个线程,从文件中加载数据。我正在考虑使用invokeLater()方法。但我想我在某个地方搞砸了,不知道是哪里。
这是我的帖子:
public class LoadBooks extends Thread{
private ArrayList<Book> books;
@Override
public void run() {
try
{
FileInputStream fis = new FileInputStream("SaveBooks.ser");
ObjectInputStream ois = new ObjectInputStream(fis);
books = (ArrayList<Book>) ois.readObject();
fis.close();
ois.close();
}catch(Exception e)
{
}
}
public ArrayList<Book> getBook() {
return books;
}
}
我是这样使用线程的:
if(e.getSource() == loadBookButton){
LoadBooks loadBooks = new LoadBooks();
loadBooks.start();
EventQueue.invokeLater(() -> books = loadBooks.getBook());
EventQueue.invokeLater(() -> updateUI(books));
}
**我认为应该如何工作:**书籍将从另一个线程中的文件加载。当书籍加载,我会得到他们从我的线程,然后我会更新我的图形用户界面。
**问题是什么?:**GUI未更新,因为 ArrayListbooks
为空。所以在某个地方有问题。我想也许我不完全理解invokeLater是如何工作的。我在java文档中查找,但没有得到太多帮助。
1条答案
按热度按时间yyhrrdl81#
假设你要做一顿饭,但是你已经到了需要面粉的地步,当你在食品室里找的时候,没有面粉。于是,你让正在花园里忙碌着干活的朋友停下手里的活,跑出去买些面粉。然后,就在你的朋友踏出门的那一刻,你试图继续做食谱,但这是什么????没有面粉!我刚让他出门去拿面粉怎么会没有?
你得等面粉来了。
你的程序也在做同样的事情。当它刚刚发送
LoadBooks
线程来获取书籍时,它正在尝试使用这些书籍。您将需要一些方法来让LoadBooks线程在书籍已经加载时发出信号,并且您需要一些方法来让GUI线程等待直到信号被传递。Semaphore
将是一个很好的。LoadBooks线程可以调用semaphore.release()
来发出图书已加载的信号,GUI线程可以调用semaphore.acquire()
来等待信号。但是等等!!
当你的朋友在买面粉的时候,你能在厨房里做点别的事情吗?如果没有--如果你除了坐在那里等待之外什么也不打算做--那么你还不如自己去拿面粉,而不是打断你朋友的工作。
实际上,如果线程A什么都不做,只是等待任务完成,那么线程A就没有任何理由将任务交给其他线程B。如果这就是你想做的,那么你也可以在线程A中完成任务。
这是一个GUI的诡计,因为也许你试图防止GUI“冻结”,而书籍正在加载。问题是,在这种情况下,如果GUI没有冻结,它会做什么?
对这个问题最简单的回答是让GUI显示一个modal dialog框,类似于“加载书籍”,并且在书籍加载之前不显示任何让用户执行其他操作的控件。如果你很友好的话,你可以在对话框中显示一个进度条,告诉他们需要等待多长时间。也许如果你真的很好,你甚至可以给予他们一个“中止”按钮,如果他们决定不等待,退出程序。
不幸的是,我不能说太多关于如何做这些事情。我从来都不是一个GUI程序员,我可能已经有十年没有在Java中做过任何事情了。