Java runnable中的无限循环失效?

Java runnable中的无限循环失效?,java,multithreading,loops,queue,runnable,Java,Multithreading,Loops,Queue,Runnable,一些简化的代码来说明我的问题: public class QueriesQueueRunnable implements Runnable { private List<String> queue = new ArrayList<String>(); @Override public void run() { while(true){ if (!this.getQueue().isEmpty()) {

一些简化的代码来说明我的问题:

public class QueriesQueueRunnable implements Runnable {

    private List<String> queue = new ArrayList<String>();


    @Override
    public void run() {
        while(true){
            if (!this.getQueue().isEmpty()) {
                    System.out.println(this.getQueue().get(0));
                    this.getQueue().remove(0);

            }
        }
    }
}
公共类QueriesQueueRunnable实现Runnable{
私有列表队列=新的ArrayList();
@凌驾
公开募捐{
while(true){
如果(!this.getQueue().isEmpty()){
System.out.println(this.getQueue().get(0));
this.getQueue().remove(0);
}
}
}
}

QueriesQueueRunnable QueriesQueueRunnable=新建QueriesQueueRunnable();
线程线程=新线程(queriesQueueRunnable).start();
对于(int i=0;i<1000;i++){
如果(i==500){
试一试{
睡眠(5000);
}捕获(中断异常例外){
Thread.currentThread().interrupt();
}
}
queryQueueRunnable.getQueue().add(String.valueOf(i));
}
输出仅在i==499迭代之前显示。为什么?这就像是执行脱离了可运行循环


Java 1.7

当您的代码处于睡眠状态时,另一个线程无休止地旋转,毫无结果,这使得它容易受到JIT编译器的优化。由于该线程无法知道正在更新
queue
,因此优化器假定
queue.isEmpty()
将永远返回
true
,并完全跳过检查

避免此问题的一种方法是将
队列
字段
设置为volatile
,这会通知JVM其他线程可以同时修改该值:

private volatile List<String> queue = new ArrayList<String>();
private volatile List queue=new ArrayList();
请注意,尽管这将解决您的特定问题,但您的代码仍然远不是线程安全的,因为
ArrayList
不适用于并发访问


还要注意的是,程序永远不会完成,除非您将次线程设为a。

当您的代码处于睡眠状态时,另一个线程会无休止地旋转,并且毫无结果,这使得它容易受到JIT编译器的优化。由于该线程无法知道正在更新
queue
,因此优化器假定
queue.isEmpty()
将永远返回
true
,并完全跳过检查

避免此问题的一种方法是将
队列
字段
设置为volatile
,这会通知JVM其他线程可以同时修改该值:

private volatile List<String> queue = new ArrayList<String>();
private volatile List queue=new ArrayList();
请注意,尽管这将解决您的特定问题,但您的代码仍然远不是线程安全的,因为
ArrayList
不适用于并发访问


还请注意,除非您将次线程设为a,否则您的程序将永远不会完成。

您是否等待了整整五秒钟?是否有任何错误消息,或者它只是挂起?
Thread Thread=new Thread(queryQueueRunnable).start()是一个编译错误。我已经等了五秒钟是的。没有任何错误。输出刚好在499停止。你等了整整五秒钟了吗?是否有任何错误消息,或者它只是挂起?
Thread Thread=new Thread(queryQueueRunnable).start()是一个编译错误。我已经等了五秒钟是的。没有任何错误。输出在499中停止。那么我应该使用Vector和synchronized使代码线程安全吗?@user2132478如果使用同步,则不需要向量,但如果使用Vector,则仍需要围绕If-Then逻辑进行同步。但是您最好使用包中的并发队列。那么我应该使用Vector和synchronized使代码线程安全吗?@user2132478如果使用同步,您不需要向量,但是如果使用Vector,您仍然需要围绕If-Then逻辑进行同步。但您最好使用包中的并发队列。