【问题标题】:While loop in thread seems to not be running虽然线程中的循环似乎没有运行
【发布时间】:2024-05-16 16:45:02
【问题描述】:

我一直在做一个有两个线程的小项目。 一个生成内容并将其放置在队列中(在静态上下文中)。 另一个线程运行并等待队列中的内容做某事。

问题:

当第二个线程正在等待将某些东西放入队列中时,它似乎没有运行,我将尝试显示这一点。

我只是好奇这里发生了什么。

_slices 是一个队列:Queue<E> _slices = new LinkedList<E>();

线程 2 run():

while ( true ) {
    if ( !Main._slices.isEmpty() ) {
            System.out.println( "Something in the Queue!" );
       } else if ( Main.doneQueuing ) {
            break;
       }
}

一旦将元素添加到队列中,上面的代码将不会执行任何操作。


现在,这段代码可以工作了:

while ( true ) {
    System.out.println( "As long as a process is done here it works" );
    if ( !Main._slices.isEmpty() ) {
            System.out.println( "Something in the Queue!" );
       } else if ( Main.doneQueuing ) {
            break;
       }
}

【问题讨论】:

  • 这意味着队列没有被填充。检查填充队列的代码并确保两个队列引用都指向同一个队列实例。
  • _slices的类型是什么?
  • @AniketThakur 队列与此无关,正如我上面所说,有一个案例有效。
  • @nosid 它是队列
  • 我的意思是队列_slices 总是空的。因此代码流永远不会进入if 语句。因此检查填充此队列的代码。

标签: java multithreading parallel-processing


【解决方案1】:

根据提供的信息,我只能猜测。我想您的代码如下所示。数据结构_slices是线程间共享的,有一个方法push可以在共享数据结构中添加一个元素并在一个线程中执行。还有一个方法poll,检查数据结构是否不为空,并在另一个线程中执行。

class Foo {
    Queue<String> _slices = new ArrayDeque<>();
    void push(String element) {
        _slices.add(element);
    }
    void poll() {
        while (!_slices.empty()) {
            // ...
        }
    }
}

在上面的例子中,有一个所谓的数据竞争。这意味着 Java 编程语言不保证执行顺序一致。还是有一些保证的。但是,它们相当复杂。

为了避免数据竞争,您应该使用支持并发的数据结构,例如ConcurrentLinkedQueueLinkedBlockingQueue。或者你应该在你的代码中使用一些同步机制,例如同步块。

【讨论】:

  • 但是如果if语句之前有进程(比如println),为什么依赖线程会识别出添加了一个元素(大小不再为0)。
  • @MichaelMitchell:因为在 println 中也有一些同步。这不会消除 数据竞争。然而,它改变了竞态条件的概率。
  • 我认为这有点超出我目前的理解。我会同意你的提议。感谢您的宝贵时间。
【解决方案2】:

LinkedList 不是线程安全的。你必须锁定你自己。

让我们试试ConcurrentLinkedQueueLinkedBlockingQueue

【讨论】: