【java面试100问】79 如何用两个线程轮流输出0到200的值?

文摘   2025-01-11 07:31   天津  

 

这个过程涉及到线程间的协作,通常我们会使用像Objectwait()notify()方法,或者其他同步工具如SemaphoreLock等来实现。

但为了方便理解,我们用最基础的synchronizedwait()notify()方法来演示。

思路讲解

  1. 1. 共享资源:首先,我们需要一个共享资源,让两个线程都能访问和修改它。

这里我们可以用一个整数变量来表示当前要输出的数字。

  1. 2. 线程间通信:为了让两个线程轮流输出数字,我们需要在某个线程输出数字后,通知另一个线程继续输出,这就需要用到线程间的通信机制。
  2. 3. 同步控制:为了防止两个线程同时修改共享资源导致数据混乱,我们需要对共享资源进行同步控制。

示例代码

public classAlternatePrint {
    
    privatestaticfinalObjectlock=newObject();
    privatestaticbooleanisThread1Turn=true;  // 用于标记轮到哪个线程打印
    privatestaticintnumber=0;  // 共享资源,当前要输出的数字

    publicstaticvoidmain(String[] args) {
        Threadthread1=newThread(newRunnable() {
            @Override
            publicvoidrun() {
                while (true) {
                    synchronized (lock) {
                        // 检查是否是线程1的回合
                        while (!isThread1Turn) {
                            try {
                                lock.wait();  // 不是线程1的回合,等待
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                        
                        // 打印数字
                        if (number > 200) {
                            lock.notify();  // 通知另一个线程,但自己不再继续
                            break;
                        }
                        System.out.println("Thread1: " + number);
                        number++;
                        
                        // 标记为线程2的回合
                        isThread1Turn = false;
                        lock.notify();  // 通知线程2继续
                    }
                }
            }
        });

        Threadthread2=newThread(newRunnable() {
            @Override
            publicvoidrun() {
                while (true) {
                    synchronized (lock) {
                        // 检查是否是线程2的回合
                        while (isThread1Turn) {
                            try {
                                lock.wait();  // 不是线程2的回合,等待
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                        
                        // 打印数字
                        if (number > 200) {
                            lock.notify();  // 通知另一个线程,但自己不再继续
                            break;
                        }
                        System.out.println("Thread2: " + number);
                        number++;
                        
                        // 标记为线程1的回合
                        isThread1Turn = true;
                        lock.notify();  // 通知线程1继续
                    }
                }
            }
        });

        // 启动两个线程
        thread1.start();
        thread2.start();
    }
}

详细讲解

  1. 1. 共享资源
  • • number:表示当前要输出的数字,初始值为0。
  • • isThread1Turn:一个布尔变量,用于标记当前轮到哪个线程输出。

true表示线程1的回合,false表示线程2的回合。

  1. 2. 同步控制
  • • 使用synchronized (lock)块来确保同一时间只有一个线程能执行里面的代码,防止数据竞争。
  • • lock是一个公共的锁对象,两个线程都用它来同步。
  • 3. 线程间通信
    • • lock.wait():使当前线程等待,直到其他线程调用lock.notify()
    • • lock.notify():唤醒一个在此锁对象监视器上等待的线程。
  • 4. 流程
    • • 线程1和线程2分别在自己的run方法中执行一个无限循环。
    • • 每次循环开始时,线程会检查是否轮到自己输出(通过isThread1Turn变量)。
    • • 如果不是自己的回合,就调用lock.wait()等待。
    • • 如果是自己的回合,就输出当前数字,并将数字加1,然后改变isThread1Turn的值,并调用lock.notify()唤醒另一个线程。
    • • 当数字超过200时,线程退出循环。

    这样,两个线程就能轮流输出0到200的值了。

    这个示例展示了如何通过synchronizedwait()notify()来实现线程间的协作和通信,希望对你有所帮助!

     


    希望文章能给大家带来点技术收获。也希望大家能够点赞收藏转发,让知识成为大家的财富。你的支持,是我最大的动力!

      

    你诺喜欢,请点个关注

    大家可以发送消息:202501

    领取计算机黑皮书191本(1月有效)

    每晚8:30分享VIP资源

    扫码加个人V拉你进群(备注IT资源)


    推荐文章:

    推荐java面试100题讲解源文件

    夏壹分享
    系统化技术讲解,每日精进,为后端技术人员打造的知识充电站!
     最新文章