Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/364.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
避免Java编译器对循环和if语句进行优化_Java_Multithreading - Fatal编程技术网

避免Java编译器对循环和if语句进行优化

避免Java编译器对循环和if语句进行优化,java,multithreading,Java,Multithreading,我有一个线程,它的主要目的是处理列表中的项目。这是在循环内完成的: while (!Thread.currentThread().isInterrupted()) { if (!jobs.isEmpty()) { final Job current = jobs.remove(0); current.start(); } } 当螺纹未中断时,应检查列表中是否有作业,如果有,应执行作业 但是这段代码是由编译器(或JIT?)优化的,并且永远不会到达i

我有一个线程,它的主要目的是处理列表中的项目。这是在循环内完成的:

while (!Thread.currentThread().isInterrupted()) {
    if (!jobs.isEmpty()) {
        final Job current = jobs.remove(0);
        current.start();
    }
}
当螺纹未中断时,应检查列表中是否有作业,如果有,应执行作业

但是这段代码是由编译器(或JIT?)优化的,并且永远不会到达if语句的主体——即使后面有条目。如果我在If块之前添加一些方法调用,它就会工作。循环是必需的,因为线程是在
ExecutorService
中运行的,我希望能够停止它的执行。那么,我如何避免这种优化呢

更新

我基本上就是这么做的:

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Test {

    private final Worker worker = new Test.Worker();
    private final ExecutorService producer = Executors.newSingleThreadExecutor();

    public static void main(final String[] args) {
        new Test().start();
    }

    public void start() {
        producer.execute(new Runnable() {

            @Override
            public void run() {
                final int cnt = 0;

                worker.add("Message " + cnt);

                try {
                    Thread.sleep(500);
                } catch (final InterruptedException e) {
                    e.printStackTrace();
                }
            }

        });

        worker.start();
    }

    public class Worker {

        private final List<String> messages = new ArrayList<>();
        private final ExecutorService consumer = Executors.newSingleThreadExecutor();

        public synchronized void add(final String msg) {
            messages.add(msg);
        }

        public synchronized void start() {
            consumer.execute(new Runnable() {

                @Override
                public void run() {
                    while (!Thread.currentThread().isInterrupted()) {
                        System.out.print("");

                        if (!messages.isEmpty()) {
                            System.out.println(messages.remove(0));
                        }
                    }
                }

            });
        }

    }

}
import java.util.ArrayList;
导入java.util.List;
导入java.util.concurrent.ExecutorService;
导入java.util.concurrent.Executors;
公开课考试{
私有最终工作者=新的Test.Worker();
private final Executor服务生产者=Executors.newSingleThreadExecutor();
公共静态void main(最终字符串[]args){
新测试().start();
}
公开作废开始(){
producer.execute(新的Runnable(){
@凌驾
公开募捐{
最终int cnt=0;
worker.add(“消息”+cnt);
试一试{
睡眠(500);
}捕获(最终中断异常e){
e、 printStackTrace();
}
}
});
worker.start();
}
公社工人{
私有最终列表消息=新建ArrayList();
private final Executor服务使用者=Executors.newSingleThreadExecutor();
公共同步无效添加(最终字符串msg){
添加消息(msg);
}
公共同步的void start(){
consumer.execute(新的Runnable(){
@凌驾
公开募捐{
而(!Thread.currentThread().isInterrupted()){
系统输出打印(“”);
如果(!messages.isEmpty()){
System.out.println(messages.remove(0));
}
}
}
});
}
}
}

您没有问过的问题是,“做我想做的事情的合理方法是什么?”,就是在您的
工作中使用or。您经常使用CPU时间轮询
作业
集合并检查
中断
标志。并发集合类有一些方法可以轮询集合,而无需经常使用CPU,它们可以正确处理中断。

您没有问过的问题是,“我试图做的事情的合理方法是什么?”,就是在
作业中使用or。您经常使用CPU时间轮询
作业
集合并检查
中断
标志。并发集合类具有轮询集合的方法,而无需持续使用CPU,它们将正确处理中断。

首先,JIT编译器不太可能优化掉
if
语句。如果有,那将是一个编译器错误

一种更可能的解释是,
if
主体没有被执行,因为该条件从来都不是
true
;i、 e.
作业
队列(或其他)始终为空。。。根据
isEmpty()

如果我将System.out.println(“未中断”);添加到“如果一切正常,控制台总是输出”未中断“

这可能是由于其他原因。例如,在循环中执行一些I/O可能意味着其他线程有机会将某些内容放入队列

“循环是必需的,因为线程在ExecutorService中运行,我希望能够停止其执行。”

事实上,这是没有必要的。有更好的方法可以做到这一点。比如说

  • 作业
    消息
    或任何内容更改为实现的类。(例如,
    ArrayBlockingQueue
    将为您提供一个有界队列(如果您需要的话)

  • 摆脱循环

  • 摆脱
    isEmpty
    测试

  • 用调用
    take()
    替换
    remove(0)

  • take()
    调用将被阻止,直到它成功地从队列中删除某个线程…或者当前线程被中断。在后一种情况下,将抛出
    InterruptedException


    这可能比在紧循环中轮询中断标志和队列更可靠、更高效。

    首先,JIT编译器不太可能优化掉
    if
    语句。如果这样做了,那将是一个编译器错误

    一种更可能的解释是,
    if
    主体没有被执行,因为条件从来都不是
    true
    ;即
    作业
    队列(或任何东西)总是空的…根据
    isEmpty()

    如果我将System.out.println(“未中断”);添加到“如果一切正常,控制台总是输出”未中断“

    这可能是由于其他原因造成的。例如,在循环中执行一些I/O可能意味着其他线程有机会将某些内容放入队列

    “循环是必需的,因为线程在ExecutorService中运行,我希望能够停止其执行。”

    事实上,这是没有必要的。有更好的方法来做到这一点。例如

  • 更改
    作业
    消息
    或任何实现的类(例如,
    ArrayBlockingQueue
    将为您提供一个有界队列,如果您需要的话)

  • 把厕所清理掉