作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有下面的程序来对 3 个线程进行排序。例如,首先应该打印第一个线程,然后是第二个线程,然后是第三个线程。但下面的程序实际上并没有这样做,也没有打印一些随机序列。我在 stackoverflow 本身上看到了一些程序,它们执行并尝试按顺序打印。
但我真的很努力去理解为什么下面的程序不工作以及我无法理解的是什么。
package my.tutorial.java;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
public class SequenceThreads {
private static final Object lock = new Object();
static class Task implements Runnable {
private final String tName;
private final int turnId;
private static int nextTurn = 1;
public Task(String tName, int turnId) {
this.tName = tName;
this.turnId = turnId;
}
@Override
public void run() {
while (true) {
synchronized (lock) {
if (nextTurn != turnId) {
try {
// System.out.println(tName + " went waiting " + nCount);
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// System.out.println(tName + " went waiting");
System.out.println(tName + " Executed ");
++nextTurn;
if (nextTurn == 4)
nextTurn = 1;
// System.out.println(nextTurn);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
lock.notify();
}
}
}
}
public static void main(String[] args) throws InterruptedException {
final Executor executor = Executors.newFixedThreadPool(3);
//AtomicInteger nCount = new AtomicInteger(1);
final Task task1 = new Task("T1", 1);
final Task task2 = new Task("T2", 2);
final Task task3 = new Task("T3", 3);
executor.execute(task1);
executor.execute(task2);
executor.execute(task3);
}
}
预期的结果应该是
T1 Executed
T2 Executed
T3 Executed
T1 Executed
T2 Executed
T3 Executed
但实际结果是
T1 Executed
T2 Executed
T1 Executed
T1 Executed
T3 Executed
T3 Executed
T1 Executed
T3 Executed
T3 Executed
最佳答案
您的代码有 2 个问题。
1.) 您使用 if
语句中的 nextTurn != turnId
检查是否轮到线程打印。这意味着如果一个线程到达这个if
,就轮不到线程了,它等待一次,然后可以再次被唤醒,它可能仍然轮不到那个线程,但它不会再次检查,只是继续乱序执行。
要解决这个问题,请将此 if
转换为 while
。
2.) notify()
不会唤醒所有等待的线程。这意味着您可能会遇到错误的线程被唤醒的情况,检查并发现还没有轮到该线程,然后再次进入 hibernate 状态,然后永远不会到达 notify()
调用,所以正确的线程永远不会被唤醒。在那种情况下,我们将解除锁定,除非发生虚假唤醒。
为此,您可以改用 notifyAll()
。
在修复了这两件事后,我看到了预期的输出:
T1 Executed
T2 Executed
T3 Executed
T1 Executed
T2 Executed
T3 Executed
T1 Executed
T2 Executed
T3 Executed
...
关于java - 在我的程序中线程没有按顺序打印,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56501323/
我是一名优秀的程序员,十分优秀!