避免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
将为您提供一个有界队列,如果您需要的话)
把厕所清理掉