生产者线程卡住了,但没有阻塞

时间:2013-02-17 04:45:16

标签: java multithreading consumer producer

我有一个生产者 - 消费者的线程集,但根据JConsole堆栈跟踪,生产者被卡在不是 .put()的一行代码上。 / p>

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! ******************************");
                }
            }
        }
    }
}

根据堆栈跟踪,它只是停留在while(true)行,而不是通过循环,即使它应该。

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)

第25行是while(true) {行。

1 个答案:

答案 0 :(得分:0)

getTick()线程是否安全?即是否有一个同步的关键字,一些形式的锁,一个易失性读或一个原子变量在去往刻度值的路上?如果没有,您的线程可能看不到对滴答计数器进行的并发更改。中断和调试可能会强制显示这些更改。

此外,您的制作人似乎不应等待成功的queue.put(),而是让应用程序进入下一个时间段。 myWorld.myApp.getTick()阻止了吗?如果没有,你的代码将无休止地循环,除非:

  • 还有其他线程同时修改tick
  • 你的线程被暂停,另一个唤醒线程修改了勾号

如果有可能发生变化,使用无限循环检查条件的变化(也就是轮询/旋转等待)才有意义。

我建议在对象waitForTick(int tick)中实施阻止并安全地公布myWorld.myApp。除了线程安全集合之外,还有其他并发组件,如信号量,障碍等,可用于同步不同的线程。