【发布时间】:2017-01-10 22:17:05
【问题描述】:
下面的代码sn-p执行两个线程,一个是简单的定时器每秒记录一次,第二个是无限循环执行余数运算:
public class TestBlockingThread {
private static final Logger LOGGER = LoggerFactory.getLogger(TestBlockingThread.class);
public static final void main(String[] args) throws InterruptedException {
Runnable task = () -> {
int i = 0;
while (true) {
i++;
if (i != 0) {
boolean b = 1 % i == 0;
}
}
};
new Thread(new LogTimer()).start();
Thread.sleep(2000);
new Thread(task).start();
}
public static class LogTimer implements Runnable {
@Override
public void run() {
while (true) {
long start = System.currentTimeMillis();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// do nothing
}
LOGGER.info("timeElapsed={}", System.currentTimeMillis() - start);
}
}
}
}
这给出了以下结果:
[Thread-0] INFO c.m.c.concurrent.TestBlockingThread - timeElapsed=1004
[Thread-0] INFO c.m.c.concurrent.TestBlockingThread - timeElapsed=1003
[Thread-0] INFO c.m.c.concurrent.TestBlockingThread - timeElapsed=13331
[Thread-0] INFO c.m.c.concurrent.TestBlockingThread - timeElapsed=1006
[Thread-0] INFO c.m.c.concurrent.TestBlockingThread - timeElapsed=1003
[Thread-0] INFO c.m.c.concurrent.TestBlockingThread - timeElapsed=1004
[Thread-0] INFO c.m.c.concurrent.TestBlockingThread - timeElapsed=1004
我不明白为什么无限任务会阻塞所有其他线程 13.3 秒。我尝试更改线程优先级和其他设置,但没有任何效果。
如果您有任何解决此问题的建议(包括调整操作系统上下文切换设置),请告诉我。
【问题讨论】:
-
@Marthin 不是 GC。这是 JIT。使用
-XX:+PrintCompilation运行时,延长延迟结束时我得到以下信息:TestBlockingThread::lambda$0 @ 2 (24 bytes) 跳过编译:普通无限循环(在不同层重试) -
它在我的系统上重现,唯一的变化是我用 System.out.println 替换了日志调用。似乎是调度程序问题,因为如果您在 Runnable 的 while(true) 循环中引入 1ms 睡眠,则另一个线程中的暂停就会消失。
-
不是我推荐的,但是如果你使用
-Djava.compiler=NONE禁用 JIT,它就不会发生。 -
您可以为单个方法禁用 JIT。见Disable Java JIT for a specific method/class?
-
这段代码中没有整数除法。请修正您的标题和问题。
标签: java multithreading