Java多线程 阿里面试题 两个线程交替打印0到100的奇偶数

文章目录

      • 使用synchronized 来实现两个线程奇偶数的交替打印(效率较低)
      • 使用wait notify 让两个线程交替打印出0到100的奇偶数(效率高)

使用synchronized 来实现两个线程奇偶数的交替打印(效率较低)

如下的代码为 使用synchronized 同步代码块, 来实现两个线程交替打印0到100的奇偶数

package com.thread.threadobjectclasscommonmethods;

/**
 * 类名称:WaitNotifyPrintOddEvenSyn
 * 类描述:  用synchronized 来实现 两个线程 奇偶数的交替打印
 *
 * @author: https://javaweixin6.blog.csdn.net/
 * 创建时间:2020/8/29 20:02
 * Version 1.0
 */
public class WaitNotifyPrintOddEvenSyn {
     

    private static int count = 0;
    private static final Object lock = new Object();

    public static void main(String[] args) {
     
        new Thread(() -> {
     
            while (count < 100) {
     
                synchronized (lock) {
     
                    // 用 & 1位运算, 如果 与1的位运算为0 , 代表为偶数
                    if ((count & 1) == 0) {
     
                        System.out.println(Thread.currentThread().getName() + " : " + count++);
                    }
                }
            }

        },"偶数").start();

        new Thread(() -> {
     
            while (count < 100) {
     
                synchronized (lock) {
     
                    // 用 & 1位运算, 如果 与1的位运算为1 , 代表为奇数
                    if ((count & 1) == 1) {
     
                        System.out.println(Thread.currentThread().getName() + " : " + count++);
                    }
                }
            }

        },"奇数").start();
    }
}

控制台打印如下, 成功的实现了需求 .
Java多线程 阿里面试题 两个线程交替打印0到100的奇偶数_第1张图片
虽然上面的代码, 成功的实现了需求, 但是使用synchronized 代码块的方法, 效率是比较低的, 可能会出现偶数或者奇数的线程, 一直获取到了锁, 但是此时, 这个数不是偶数或者奇数, 那么就即使进入了synchronized 修饰的同步代码块中, 由于不满足if判断条件, 导致此时获取的锁是废的 ,而且 这种重复获取无效的锁的情况看来会发生很多次, 导致了效率的低下.

使用wait notify 让两个线程交替打印出0到100的奇偶数(效率高)

使用wait notify 让两个线程交替打印出0到100的奇偶数的核心思路

  1. 拿到锁就直接打印
  2. 打印完, 唤醒另外一个线程后,自己就调用wait进入等待状态

此方法相比较于synchronized 就不会出现获得了锁之后由于无法满足条件而浪费了获得的锁情况.
效率更高.
并且需要注意的是, 在调用wait状态之前, 需要判断任务是否已经完成 否则线程会一直阻塞.
因为在调用notify之前, 获得锁之前, 也会判断是否任务已经完成, 如果任务完成了, 那么就不会进入同步代码块. 导致无法唤醒.

package com.thread.threadobjectclasscommonmethods;

/**
 * 类名称:WaitNotifyPrintOddEvenWait
 * 类描述:  使用wait notify 让两个线程交替打印出0到100的奇偶数
 *
 * @author: https://javaweixin6.blog.csdn.net/
 * 创建时间:2020/8/29 20:19
 * Version 1.0
 */
public class WaitNotifyPrintOddEvenWait {
     
    private static int count = 0;
    private static final Object lock = new Object();

    public static void main(String[] args) {
     
        new Thread(new PrintRunner(), "偶数").start();
        //为了防止奇数线程先启动, 因此偶数线程启动后 , 休眠10ms . 保证偶数线程先打印
        try {
     
            Thread.sleep(10);
        } catch (InterruptedException e) {
     
            e.printStackTrace();
        }

        new Thread(new PrintRunner(), "奇数").start();
    }

    /**
     * 核心思路
     * 1. 拿到锁就直接打印
     * 2. 打印完, 唤醒另外一个线程后,自己就调用wait进入等待状态
     */
    static class PrintRunner implements Runnable {
     

        @Override
        public void run() {
     
            while (count <= 100) {
     
                synchronized (lock) {
     
                    //拿到锁就打印
                    System.out.println(Thread.currentThread().getName() + " " + count++);

                    //打印完, 唤醒另外一个线程后,自己就休眠
                    lock.notify();

                    //判断任务是否结束了,再去执行wait, 否则程序会一直阻塞,无法唤醒
                    if (count <= 100) {
     
                        try {
     
                            //进入等待状态, 释放锁
                            lock.wait();
                        } catch (InterruptedException e) {
     
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
    }

}

你可能感兴趣的:(Java多线程基础与核心)