我已经使用多线程在Java中实现了一个5阶段CPU指令管道模拟器。
每个阶段都是一个主要执行3个以下功能的线程,每两个阶段之间也有一个队列(容量为1)。
@Override public void run() { while (!(latchQueue.isEmpty())) { fetch(); process(); forward(); } }
模拟效果很好。这就是我被困住的地方,我希望能够只模拟指定数量的时钟周期。因此,模拟器应在达到指定的循环次数后停止/暂停。
截至目前,我已经启动了所有5个线程并让它模拟所有指令的处理,而不是按时钟周期限制它。
我怎样才能做到这一点?在达到指定的时钟周期时,是否需要暂停线程?如果是这样,我怎样才能优雅地处理暂停/停止线程?请帮助我选择最好的方法。 在此先感谢:)
答案 0 :(得分:1)
您已经在使用某些并发队列来在线程之间进行通信(确切地说它的工作原理并不清楚,因为您的代码示例非常不完整)。
因此,您可以在第一阶段计算周期,并使用相同的机制进行通信:将一个Sentinel对象推送到第一阶段的队列中,该对象代表"时间停止/暂停此线程"并且在处理时它暂停处理器(并且仍然将其转发到下一阶段,因此所有阶段将逐渐关闭)。例如,您可以扩展队列中传递的对象类型,以便层次结构包含实际有效负载对象(例如,已解码的指令等)或"命令对象"像这样停止/暂停哨兵。
另一个异步解决方案是Thread.interrupt
每个线程并在你的处理循环中添加一个中断检查 - 这主要是为了优雅地关闭,而不是支持"暂停&# 34;功能。
答案 1 :(得分:0)
以下工作会怎样?
在代表阶段的所有线程之间共享类CyclesCounter
。它有tryReserve
方法,从中获取true
意味着线程已经为其下一次运行获得了足够的“时钟周期”。获得false
意味着没有足够的周期。类是线程安全的。
在获得false
之后,或许,你的线程应该停止(即,从run()
返回) - 没有办法可以获得足够的周期(由于你的要求,因为我了解他们),直到整个会话再次运行。
class CyclesManager {
private final AtomicInteger cycles;
CyclesManager(int initialTotalCycles) {
if (initialTotalCycles < 0)
throw new IllegalArgumentException("Negative initial cycles: " + initialTotalCycles);
cycles = new AtomicInteger(initialTotalCycles);
}
/**
* Tries to reserve given nr of cycles from available total nr of cycles. Total nr is decreased accordingly.
* Method is thread-safe: total nr of is consistent if called from several threads concurrently.
*
* @param cyclesToReserve how many cycles we want
* @return {@code true} if cycles are ours, {@code false} if not -- there's not enough left
*/
boolean tryReserve(int cyclesToReserve) {
int currentCycles = cycles.get();
if (currentCycles < cyclesToReserve)
return false;
return cycles.compareAndSet(currentCycles, currentCycles - cyclesToReserve);
}
}