大约两个线程交替打印奇数和偶数

  • 本文关键字:打印 线程 两个 java
  • 更新时间 :
  • 英文 :


也就是说,下面的代码交替打印从0到100的奇数和偶数。我的循环条件是计数小于100。

为什么最终输出结果达到100?如果它不是100,那么在跳出循环之后就不能执行它。

public class WaitNotifyPrintOddEvenSyn {
    private static int count;
    private static final Object lock = new Object();
    
    //新建 2 个线程,一个只处理偶数,一个只处理奇数
    //并且用 synchronized 来通信
    public static void main(String[] args) {        
        new Thread(new Runnable() {
            @Override
            public void run() {
                while(count < 100){
                    synchronized (lock){
                        if((count & 1) == 0){
                            System.out.println(Thread.currentThread().getName() + ": " + count);
                            count++;
                        }
                    }
                }
            }
        }, "偶线程").start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                while(count < 100){
                    synchronized (lock){
                        if((count & 1) == 1){
                            System.out.println(Thread.currentThread().getName() + ": " + count);
                            count++;
                        }
                    }
                }
            }
        }, "奇线程").start();
    }
}

当变量count的值为99时发生这种情况。

考虑两个有趣的场景:

count的值为99。

现在,两个线程都通过了第一个过滤器,即if(count < 100)

现在,两个线程都将竞相获取变量lock上的锁。

设CCD_ 6和CCD_。

场景1:如果A战胜B

则if条件if((count & 1) == 0)将失败,因为count是奇数。

线程A没有打印任何内容,A释放锁,B获取锁。

现在,B打印值99,并将count的值递增到100。

预期场景1

但是,可能会出现第二种情况。

场景2:如果B战胜A,A必须等待B完成:

CCD_ 11的值为99。

现在,两个线程都通过了第一个过滤器,即if(count < 100)

在这种情况下,if条件if((count & 1) == 1)被传递为count是奇数。

B打印值99并将CCD_ 15的值增加到100。

现在,A中的if条件if((count & 1) == 0)也将通过,因为count的值是偶数,即100。

因此,线程A打印100。

那么现在,如何解决这个问题

答案:

只需在线程a的if条件中引入一个条件来检查CCD_ 18。

if((count & 1) == 0 && count<100)

看看以下实现:

public class WaitNotifyPrintOddEvenSyn {
    private static int count;
    private static final Object lock = new Object();
    
    //新建 2 个线程,一个只处理偶数,一个只处理奇数
    //并且用 synchronized 来通信
    public static void main(String[] args) {        
        new Thread(new Runnable() {
            @Override
            public void run() {
                while(count < 100){
                    synchronized (lock){
                        if((count & 1) == 0 && count<100){
                            System.out.println(Thread.currentThread().getName() + ": " + count);
                            count++;
                        }
                    }
                }
            }
        }, "偶线程").start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                while(count < 100){
                    synchronized (lock){
                        if((count & 1) == 1){
                            System.out.println(Thread.currentThread().getName() + ": " + count);
                            count++;
                        }
                    }
                }
            }
        }, "奇线程").start();
    }
}

输出:

偶线程: 0
奇线程: 1
偶线程: 2
奇线程: 3
偶线程: 4
奇线程: 5
偶线程: 6
奇线程: 7
偶线程: 8
奇线程: 9
偶线程: 10
奇线程: 11
偶线程: 12
奇线程: 13
偶线程: 14
奇线程: 15
偶线程: 16
奇线程: 17
偶线程: 18
奇线程: 19
偶线程: 20
奇线程: 21
偶线程: 22
奇线程: 23
偶线程: 24
奇线程: 25
偶线程: 26
奇线程: 27
偶线程: 28
奇线程: 29
偶线程: 30
奇线程: 31
偶线程: 32
奇线程: 33
偶线程: 34
奇线程: 35
偶线程: 36
奇线程: 37
偶线程: 38
奇线程: 39
偶线程: 40
奇线程: 41
偶线程: 42
奇线程: 43
偶线程: 44
奇线程: 45
偶线程: 46
奇线程: 47
偶线程: 48
奇线程: 49
偶线程: 50
奇线程: 51
偶线程: 52
奇线程: 53
偶线程: 54
奇线程: 55
偶线程: 56
奇线程: 57
偶线程: 58
奇线程: 59
偶线程: 60
奇线程: 61
偶线程: 62
奇线程: 63
偶线程: 64
奇线程: 65
偶线程: 66
奇线程: 67
偶线程: 68
奇线程: 69
偶线程: 70
奇线程: 71
偶线程: 72
奇线程: 73
偶线程: 74
奇线程: 75
偶线程: 76
奇线程: 77
偶线程: 78
奇线程: 79
偶线程: 80
奇线程: 81
偶线程: 82
奇线程: 83
偶线程: 84
奇线程: 85
偶线程: 86
奇线程: 87
偶线程: 88
奇线程: 89
偶线程: 90
奇线程: 91
偶线程: 92
奇线程: 93
偶线程: 94
奇线程: 95
偶线程: 96
奇线程: 97
偶线程: 98
奇线程: 99

PS:我还建议您查看和研究wait()notify()方法,并编写一个逻辑上更健壮的代码。

最新更新