我有一个简单的代码片段,并试着用它进行一些实验,但在下一个代码中,我不清楚输出数据的顺序:
public class Main {
static int n = 100;
public static synchronized int decreaseValue(){
return --n;
}
public static void main(String[] args) throws InterruptedException, IOException {
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
while(true){
try {
System.out.println("Thread1: "+ decreaseValue());
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
},"Thread1");
t1.start();
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
while(true){
try {
System.out.println("Thread2: "+ decreaseValue());
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
},"Thread2");
t2.start();
while(true){
try {
System.out.println("Main Thread: "+ decreaseValue());
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
无法理解,为什么我会按下一个顺序获得这些值:
线程1:89 线程2:90 主线:88
请注意N值而不是呼叫线的顺序:
Thread1: 99
Thread2: 98
Main Thread: 97
Main Thread: 95
Thread2: 94
Thread1: 96
Main Thread: 92
答案 0 :(得分:3)
您必须阅读必须使用synchronized
以确保正确排序或类似内容的地方。 “排序”一词与你想到的概念有不同的概念:它意味着对同步块的执行总会有一些明确的顺序。订购事先不知道,但每次都会在那里。如果没有同步,你甚至不会得到这样的保证:一个线程可以感知一个订单,另一个线程可以感知不同的订单,或者根本不感知其他线程的任何操作。
如果您担心打印输出无序,这是因为您的println
语句不在synchronized
范围内,因此可以独立于decreaseValue
的调用进行交错。
答案 1 :(得分:2)
线程并行运行。您无法预测其执行顺序。您可以设置优先级执行顺序的线程优先级。
答案 2 :(得分:1)
线程正在并发运行,没有任何东西强加它们应该调用你的decreaseValue()
函数。你会期望它们按顺序排列,因为你正在做同样的睡眠:)但是一旦线程从睡眠中启动/恢复,CPU就会将线程放在一个正在运行的队列中(创建执行顺序,这是同步保证的顺序),因此打印顺序取决于CPU如何将线程置于运行队列中。
如果您询问打印指令,控制台上的打印也会同步(但与reduceValue不在同一个程序段中)。相同的逻辑适用于打印,以减少值。
如果您希望以与递减值相同的顺序查看打印件,则可以在decreaseValue()
功能中移动打印件。但这不会影响值的递减顺序。