3 回答
TA贡献1773条经验 获得超3个赞
了解内部SwingWorker使用可能会有所帮助ExecutorService;为方便起见,它添加了临时EDT处理机制。只要您在EDT上更新GUI并同步对任何共享数据的访问,则后者等效于前者。
假设您使用的是此处建议的“ 模型–视图–控制器”模式,则模型是CPU的操作。尽管可能是不同的类,但我看不出有任何理由在不同的线程上对读卡器进行建模。相反,让处理器模型具有读卡器模型,该模型在线程上等待,并在计时器触发时更新模型。让更新的模型在将事件发布到EDT的正常过程中通知视图。让控制器根据查看手势取消和安排读卡器模型。java.util.Timer
TA贡献1797条经验 获得超4个赞
我附加到原始问题的“答案”中缺少一件事:
我正在Thread.sleep()通过单线程执行程序将耗时的工作(仅用于教学目的)交给后台线程。但是,出现了一个问题,因为后台线程正在通过轮询(用作一个Swing组件的数据模型的)List来“读取卡”,并引发了许多AWT数组索引超出范围的异常。经过几次徒劳的尝试使EDT和我的后台线程同步对列表的访问之后,我进行了调试,并将命令轮询(包装)到List(列表)并在一个小的Runnable()中更新了GUI,并使用invokeAndWait()导致当我的后台任务等待时,它们将在EDT上运行。
这是我修改后的解决方案:
private ExecutorService executorService;
:
executorService = Executors.newSingleThreadExecutor();
:
/*
* When EDT receives a request for a card it calls readCard(),
* which queues the work to the *single* thread.
*/
public void readCard() throws Exception {
executorService.execute(new Runnable() {
public void run() {
if (buffer.isEmpty()) {
/*
* fill() takes 1/4 second (simulated by Thread.sleep)
*/
buffer.fill();
}
Card card = buffer.get(); // empties buffer
/*
* Send card to CPU
*/
CPU.sendMessage(card); // <== (A) put card in msg queue
/*
* No race! Next request will run on same thread, after us.
*/
buffer.fill(); // <== (B) pre-fetch next card
return;
}
});
}
/*
* IMPORTANT MODIFICATION HERE - - -
*
* buffer fill() method has to remove item from the list that is the
* model behind a JList - only safe way is to do that on EDT!
*/
private void fill() {
SwingUtilities.invokeAndWait(new Runnable() {
/*
* Running here on the EDT
*/
public void run() {
/*
* Hopper not empty, so we will be able to read a card.
*/
buffer = readHopper.pollLast(); // read next card from current deck
fireIntervalRemoved(this, readHopper.size(), readHopper.size());
gui.viewBottomOfHopper(); // scroll read hopper view correctly
}
});
// back to my worker thread, to do 1/4 sec. of heavy number crunching ;)
// while leaving the GUI responsive
Thread.sleep(250);
:
etc.
}
添加回答
举报