2

你好我是java编程的初学者,最近我正在学习线程,我在这个程序的输出中遇到了问题。

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...,请解释为什么?

4

3 回答 3

7

线程是异步执行的——所以它们的输出自然会交织在一起,这是意料之中的。在你的情况下:

1 1 2 2 1 1 3 3

...我“加粗”的那一点是一个线程的输出,我留下的那一点是另一个线程的(开始)输出。我只能根据程序的执行方式来解决这个问题 - 例如,如果您有两个线程只打印字符“1”,则无法区分哪个线程正在打印什么字符。

请注意,数字出现的顺序和它们交织的方式是完全任意的——它可能很容易是这样的:

1 1 1 1 2 2 3 3 2 2..

...或任何其他可能的组合。不要依赖您碰巧获得的任何特定程序的顺序,它是完全未定义的。

于 2013-06-10T10:48:57.877 回答
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

于 2013-06-10T10:48:44.827 回答
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只是两个线程做同样事情的输出。

于 2013-06-10T10:55:21.050 回答