您好我是java编程的初学者,最近我正在学习Threads,我在这个程序的输出中遇到了问题。
class s1 implements Runnable
{
int x = 0, y = 0;
int addX() {x++; return x;}
int addY() {y++; return y;}
public void run() {
for(int i = 0; i < 10; i++){
System.out.println(addX() + " " + addY());
}
}
public static void main(String args[])
{
s1 run1 = new s1();
s1 run2 = new s1();
Thread t1 = new Thread(run1);
Thread t2 = new Thread(run2);
t1.start();
t2.start();
}
}
我得到这样的输出,
1 1 2 2 1 1 3 3 ... ,请解释原因?
答案 0 :(得分:7)
线程正在异步执行 - 因此它们的输出将自然地交织在一起,这是可以预期的。在你的情况下:
1 1 2 2 1 1 3 3
...我用“加粗”的位是一个线程的输出,我离开的位是另一个输出的(开始)。我只能通过程序执行的方式来解决这个问题 - 例如,如果你有两个线程只打印字符“1”,就不可能区分哪个线程正在打印什么字符。
请注意,数字的显示顺序和交错方式完全是任意的 - 它可能很容易就像:
1 1 1 1 2 2 3 3 2 2 ..
......或任何其他可能的组合。不要依赖你正好为任何特定程序获得的顺序,它是完全未定义的。
答案 1 :(得分:5)
s1
类的每个实例都有自己的变量,因此它们将相互独立地增加。如果您只创建了一个实例,则输出为1 1 2 2 3 3 ...
。
如果您打印两个线程1 1 2 2 3 3 ...
,您将看到两个流混合在一起。只要它以正确的顺序输出每个数字的正确数字,它就会按照您的期望进行。你不能指望如何安排线程。
因此,您可能会看到1 1 2 2 3 3 1 1 2 2 3 3...
或1 1 1 1 2 2 2 2 3 3 3 3...
或任何其他变体。
(有一天,如果调度程序以某种方式切片,您甚至可能会看到1 1 1 1 2 2 2 2 3 3 3 3 ...
幸运)
编辑:同时在println
来电中阅读有关线程安全的this answer。
答案 2 :(得分:0)
尝试执行此代码:
class Test extends Thread {
Test(String name) {
super(name);
}
int x = 0, y = 0;
int addX() {x++; return x;}
int addY() {y++; return y;}
public void run() {
for(int i = 0; i < 10; i++)
System.out.println(addX() + " " + addY() + ", name:" + getName());
}
public static void main(String args[]) {
Test run1 = new Test("thread1");
Test run2 = new Test("thread2");
run1.start();
run2.start();
}
}
您将获得与此类似的输出:
1 1, name:thread2
2 2, name:thread2
1 1, name:thread1
2 2, name:thread1
3 3, name:thread2
3 3, name:thread1
这是因为踏板不会同步执行。你不知道什么时候会被执行。在您的代码中 1 1 然后再次 1 1 只是两个执行相同操作的线程的输出。