Java 生产者线程被卡住,但没有阻塞
我有一个生产者-消费者线程集,但根据JConsole堆栈跟踪,生产者被卡在了一行不是Java 生产者线程被卡住,但没有阻塞,java,multithreading,consumer,producer,Java,Multithreading,Consumer,Producer,我有一个生产者-消费者线程集,但根据JConsole堆栈跟踪,生产者被卡在了一行不是.put()的代码上 class Producer implements Runnable { private final BlockingQueue<CopyOnWriteArrayList<Creature>> queue; private World myWorld; Producer(BlockingQueue<CopyOnWriteArrayLis
.put()
的代码上
class Producer implements Runnable {
private final BlockingQueue<CopyOnWriteArrayList<Creature>> queue;
private World myWorld;
Producer(BlockingQueue<CopyOnWriteArrayList<Creature>> q, World myWorld) {
queue = q;
this.myWorld = myWorld;
}
public void run() {
int nextTick = myWorld.myApp.getTick(); //'tick' is the current frame our main loop is on.
while (true) {
if (myWorld.myApp.getTick() >= nextTick) { //if our world has updated to the next frame…
nextTick = myWorld.myApp.getTick() + 1; //increment the next frame to wait for
try {
for (int i = 0; i < myWorld.getCellController()
.getColumns(); i++) {
for (int j = 0; j < myWorld.getCellController()
.getRows(); j++) {
queue.put(myWorld.getCellController().Cells.get(i)
.get(j));
}
}
} catch (InterruptedException ex) {
System.out.println("INT! ******************************");
} catch (NullPointerException ex) {
System.out.println("NULL! ******************************");
} catch (ClassCastException ex) {
System.out.println("CAST! ******************************");
} catch (IllegalArgumentException ex) {
System.out.println("ARG! ******************************");
}
}
}
}
}
第25行是而(true){
行。是getTick()
thread safe(线程安全)?即,在到达刻度值的过程中是否存在同步关键字、某种形式的锁、易失性读取或原子变量?如果没有,线程可能看不到对刻度计数器进行的并发更改。中断和调试可能会迫使这些更改可见
此外,您的制作人似乎不应该等待成功的queue.put()
,而是等待应用程序前进到下一个刻度。myWorld.myApp.getTick()
阻塞?否则,您的代码将无休止地循环,除非:
- 还有其他线程同时修改勾号
- 你的线程被挂起,另一个被唤醒的线程修改勾号
我建议实现一个阻塞并安全发布
waitForTick(int-tick)
在对象myWorld.myApp
中。除了线程安全集合之外,还有其他可用于同步不同线程的并发组件,如信号量、屏障等。您使用的是哪种阻塞队列实现?我已经尝试了ArrayBlockingQueue
和LinkedBlockingQueue
,它可以挂起。请将(JConsole)堆栈跟踪添加到您的问题中。您确定执行路径到达了put
行吗?在put
行周围有条件语句(if/for)。是的,我非常确定。每当我在该行调试和中断,并手动推进它时,条件语句(if)的计算结果为true(无需我做任何其他事情),我可以手动退出代码。getTick()线程安全吗?否。它只返回int
变量,该变量在每次单独的主线程(游戏控制器)运行时inc'd+1循环迭代。主线程是唯一一个修改int
勾号的线程。每当我调试和中断时,getTick
值都会增加到足以满足if语句的程度。生产者线程总是在该条件语句上循环,所以我不明白为什么它最终不会看到更改tgetTick()。
Stack trace:
Name: Producer
State: RUNNABLE
Total blocked: 0 Total waited: 196,958
Stack trace:
concurrency.Producer.run(Setup.java:25)
java.lang.Thread.run(Thread.java:680)