我将本练习用作教学工具,以帮助我掌握一些Java GUI编程概念。我要寻找的是一种一般的理解,而不是针对一个特定问题的详细解决方案。我希望编码这种“正确的”方法将教给我很多有关如何解决将来的多线程问题的知识。如果对于这个论坛来说太笼统了,那么它可能属于Programmers吗?
我在模拟读卡器。它具有GUI,可让我们将卡装载到料斗中并按Start(开始),依此类推,但它的主要“客户端”是CPU,在单独的线程上运行并请求卡。
读卡器维护一个缓冲区。如果有卡请求进入并且缓冲区为空,则读卡器必须从料斗读取卡(这需要1/4秒,即1962)。在将卡读入缓冲区后,读卡器将缓冲区发送到CPU,并在下一个请求之前立即启动另一个缓冲区加载操作。
如果不仅缓冲区是空的,而且料斗中没有卡,那么我们必须等到操作员将一个平台放在料斗中并按下启动键(这始终会启动缓冲区加载操作)。
在我的实现中,卡请求以invokeLater() Runnables在EDT上排队的形式发送到读卡器。在myRunnable.run()时间,无论是一个缓冲器将可用(在这种情况下,我们可以将其发送到CPU和开球另一个缓冲器负载操作),或缓冲区将是空的。如果是空的怎么办?
两种可能性:(a)飞行中已经进行了缓冲加载操作,或者(b)储卡器为空(或尚未启动)。无论哪种情况,都不能让EDT等待。工作(和等待)必须在后台线程上完成。
为了简单起见,我尝试生成一个SwingWorker来响应每个卡请求,而不管缓冲区的状态如何。伪代码为:
SwingWorker worker = new SwingWorker<Void, Void>() {
public Void doInBackground() throws Exception {
if (buffer.isEmpty()) {
/*
* fill() takes 1/4 second (simulated by Thread.sleep)
* or possibly minutes if we need to have another
* card deck mounted by operator.
*/
buffer.fill();
}
Card card = buffer.get(); // empties buffer
/*
* Send card to CPU
*/
CPU.sendMessage(card); // <== (A) put card in msg queue
/*
* Possible race window here!!
*/
buffer.fill(); // <== (B) pre-fetch next card
return null;
}
};
worker.execute();
这产生了一些奇怪的计时效果-我怀疑是buffer.fill()由于可能发生如下情况的比赛:如果在(A)和(B)之间,CPU收到了卡,发送了另一个请求,并有另一个SwingWorker线程代表它生成,则可能有两个线程同时尝试填充缓冲区。[删除(B)处的预取调用解决了该问题。]
所以我认为每次读取都产生一个SwingWorker线程是错误的。卡的缓冲和发送必须在单个线程中序列化。该线程必须尝试预取缓冲区,并且如果我们的卡用完了并且必须等待将更多的内存放入料斗中,则必须能够等待并恢复。我怀疑SwingWorker拥有长时间运行的后台线程才能处理此问题,但我还没有到位。
假设要使用SwingWorker线程,我应该如何实现这一点,消除EDT的延迟,允许该线程阻塞等待装满料斗并处理在另一个卡请求到达之前或之后是否完成缓冲区填充的不确定性?
慕容3067478
繁星coding
相关分类