我正在用 Java/Swing 编写一台旧计算机的模拟器,我想我已经确定了我遇到的设计问题。尽管这个应用程序很奇特,但我怀疑有人会找到解决这个问题的“模式”。
我应该补充一点,我仍然是 OOP、GUI 和设计模式的初学者。
该机器有一个 GUI 线程 (Console) - 带有按钮和开关,以及一个模型线程 (CPU),控制台与模型线程 (CPU) 通信以使控制台事件改变 CPU 的状态。当然,控制台是来自 AWT 事件队列的事件驱动。控制台通过在 CPU 接收的优先阻塞队列上排队消息来与 CPU 通信。因此,CPU 也被构造为事件循环。到现在为止还挺好。
问题是,当您在控制台上按下 START 时,您希望 CPU 开始执行其内存中的任何程序。它仍然需要响应来自控制台的开关抛出和按钮推动(例如 STOP),但它主要需要坐在那里并通过其指令获取-解码-执行循环进行旋转。
甚至这在一段时间内也没有问题:我有一个名为Cycle()的方法,它将执行当前指令的一个特定“周期”,然后返回,立即重新调度以执行下一个周期。我将 Cycle() 的调用放在 CPU 的运行循环中,并在每个循环后轮询消息队列。如果 CPU 停止,运行循环将简单地等待消息队列。
现在:我正在执行 I/O 指令,例如读卡。其中一个周期有必要向相关外围设备发送数据请求(其本身实现为在单独线程上运行的 GUI/模型),然后等待数据到达。这完全打破了 CPU 是一个简单的事件循环的概念,它接收消息并对其进行操作,而不会导致进程阻塞。这个新的循环将阻塞。如果操作员没有将卡片组加载到读卡器中,它可能会阻塞很长时间。
我曾考虑将指令 fetch-decode-execute 循环分解为一个单独的“工作”线程,但我认为这不太合适,因为工作线程(据我所知)旨在异步运行以完成,并且运行时不要继续与其父线程交互。(事实上,我想不出为什么“工作线程”应该终止。)此外,当一个循环需要访问由于控制台按键而可以同时修改的数据时,目前不需要同步。
那么,我如何设法将“事件驱动”处理与需要在继续之前显式等待消息的传统批处理相结合呢?