static volatile boolean - 线程没有被终止

xwh*_*hyz 3 java concurrency multithreading

我编写了简单的多线程应用程序,只是为了解决并发问题,但我遇到了一个boolean变量的问题,它控制了线程中的循环.其中一个函数应该停止线程,如果队列中没有留下任何元素,我想这是我的问题,因为如果我在大括号之间添加一些东西:

while (!queue.isEmpty()) {
}
isRunning = false;
Run Code Online (Sandbox Code Playgroud)

所以它变成:

while (!queue.isEmpty()) {
    System.out.println("ASD");
}
isRunning = false;
Run Code Online (Sandbox Code Playgroud)

它工作得更好 - 程序在执行turnOff方法后终止

有任何想法吗?

这是我的应用程序的完整代码:

package test;

public class xxx {
    public static void main(String[] args) {
        Foo instance = Foo.getInstance();
        Thread x = new Thread(instance);
        x.start();

        for (int count = 1; count < 100000; count++)
            instance.addToQueue(count + "");
        instance.turnOff();
    }
}
Run Code Online (Sandbox Code Playgroud)

和:

package test;

import java.util.LinkedList;
import java.util.List;

public class Foo implements Runnable {
    private static Foo inner = null;
    private static List<String> queue = new LinkedList<String>();
    private volatile static boolean isRunning = false;

    private Foo() { }

    public static Foo getInstance() {
        if (inner == null) {
            inner = new Foo();
        }
        return inner;
    }

    public void addToQueue(String toPrint) {
        synchronized (queue) {
            queue.add(toPrint);
        }

    }

    public void removeFromQueue(String toRemove) {
        synchronized (queue) {
            queue.remove(toRemove);
        }
    }

    public void turnOff() {
        while (!queue.isEmpty()) {
        }
        System.out.println("end");
        isRunning = false;
    }

    @Override
    public void run() {
        isRunning = true;
        while (isRunning) {
            if (!queue.isEmpty()) {
                String string = queue.get(0);
                System.out.println(string);
                removeFromQueue(string);
            }

        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Isi*_*oGH 5

这是一个竞争条件问题.可能在主线程中的turnOff输入之后执行run方法(另一个线程),因此标志isRunning再次设置为true并且循环永远不会结束.

这可以解释为什么使用简单的System.out.println("ASD")变得更好:isRunning = false被延迟.