共享计数器和java线程

时间:2016-03-31 09:15:22

标签: java multithreading

我正在检查一个示例,并对其进行测试并为每次运行获得不同的输出..这是代码:

    public class Th1 implements Runnable{
        private int i=0;
        public void run(){
            try{
                Thread.sleep(1000);
                } catch (InterruptedException ex){
            }
            while(i<10){
                System.out.println(i);
                i+=1;
            } } 

    public static void main(String[] args) {
        Th1 t = new Th1();
        Thread t1 = new Thread(t);
        Thread t2 = new Thread(t);
        t1.start();
        t2.start();
    }       

这是第一次运行输出

    0
    1
    2
    3
    4
    5
    6
    7
    8
    9
    0

第二次运行输出:

    0
    1
    2
    3
    4
    5
    6
    7
    8
    9

据我所知,第一个输出的解释是每个线程都有自己的缓存,第二个线程最后开始,打印它是i(0),当它检查内存以通过增量编辑i时,它发现实际值为10,因此它变为11,并退出循环。 但为什么第二次运行只有一个零?

3 个答案:

答案 0 :(得分:2)

@Gunner@mel3kings之外 实际上,彼此并行运行的线程和OS可能允许一个线程更多时间而不是下一个线程。

情景1;

   loop     Thread1              Thread2
    t1     sleep                sleep
    t2     started to loop      started the loop
    t4     print 0              print 1
    t5     print 2              print 3
    t6     print 4              print 5
    t7     print 6              print 7
    t8     print 8              print 9
    t9     print 10             exit to loop

情景2

   loop       Thread1              Thread2
    t1     sleep                sleep
    t2     started to loop      
    t4     print 0              
    t5     print 1              
    t6     print 2              
    t7     print 3              
    t8     print 4              started loop
    t9     ..................................

场景3(也可能)

   loop       Thread1              Thread2
    t1     sleep                sleep
    t2     started to loop      started loop
    t3     print 0              send i to print
    t4     print 1              
    t5     print 2              
    t6     print 3              
    t7     print 4              
    t8     print 5              
    t9     print 6              
    t10     print 7              
    t11     print 8
    t12     print 9
    t13     exit             print 0 (delay of console output may cause that)

还有其他输出方案。

无论如何要查看其详细信息,请尝试下面带有线程名称的代码,并查看哪个线程打印每个输出

public class Th1 implements Runnable {
    private int i = 0;

    public void run() {
        String name = Thread.currentThread().getName();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException ex) {
        }
        while (i < 10) {
            System.out.println(name + ": " + i);
            i += 1;
        }
    }

    public static void main(String[] args) {
        Th1 t = new Th1();
        Thread t1 = new Thread(t);
        Thread t2 = new Thread(t);
        t1.start();
        t2.start();

    }
}

输出

Thread-1: 0
Thread-1: 1
Thread-1: 2
Thread-0: 0  //last zero may comes from here but print order is about console
Thread-1: 3  
Thread-1: 4
Thread-1: 5
Thread-1: 6
Thread-1: 7
Thread-1: 8
Thread-1: 9

答案 1 :(得分:1)

在第二次运行时,T2“太晚醒来”并且T1已经将i增加到10,因此T2将不会进入while循环。我认为第一次运行是诚实的。

答案 2 :(得分:0)

假设T1 and T2t1.start();t2.start()期间同时运行,此时i = 0T1睡眠和T2睡眠,T1醒来并继续检查我是否&lt; 10,打印出1-9,但T2醒来但仍未由JVM运行,知道一旦线程退出睡眠状态并不一定意味着它会立即运行。一旦T2运行,我仍然为0,它检查它是否&lt; 10,它打印出0,然后修改加1但是i已经改变了值,结果为11.因此不再打印

第二次运行,T1在T2执行之前结束,我已经是10.没有保证线程实际运行的时间。