蔚来手撕代码题:三个线程循环打印ABC

简介: 蔚来手撕代码题:三个线程循环打印ABC

问题如下:
image.png

https://www.nowcoder.com/discuss/493178141461041152

思路分析

三个线程交替打印 ABC 的实现方法有很多,我个人比较倾向于使用 JUC 下的 CyclicBarrier(循环栅栏,也叫循环屏障)来实现,因为循环栅栏天生就是用来实现一轮一轮多线程任务的,它的核心实现思路如下图所示:
image.png
CyclicBarrier 作用是让一组线程相互等待,当达到一个共同点时,所有之前等待的线程再继续执行,且 CyclicBarrier 功能可重复使用。
20181218144511688.gif
上图描述的就是 CyclicBarrier 每轮等待 5 个线程全部达到一个共同点时,再执行下一阶段的任务。

举个例子

比如磊哥要坐班车回老家,因为中途不允许上、下乘客,那么营运的公司为了收益最大化,就会等人满之后再发车,这个发车的触发条件就是 CyclicBarrier 中多个线程执行的共同点。等汽车达到另一个站点之后也是同样的操作,等待乘客再次坐满之后,再继续发车,CyclicBarrier 就是这样执行的,它也是可以循环使用的。

实现代码

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

/**
 * 3 个线程交替打印 ABC
 */
public class ThreadLoopPrint {
   
   
    // 共享计数器
    private static int sharedCounter = 0;
    public static void main(String[] args) {
   
   
        // 打印的内容
        String printString = "ABC";
        // 定义循环栅栏
        CyclicBarrier cyclicBarrier = new CyclicBarrier(3, () -> {
   
   
        });
        // 执行任务
        Runnable runnable = new Runnable() {
   
   
            @Override
            public void run() {
   
   
                for (int i = 0; i < printString.length(); i++) {
   
   
                    synchronized (this) {
   
   
                        sharedCounter = sharedCounter > 2 ? 0 : sharedCounter; // 循环打印
                        System.out.println(printString.toCharArray()[sharedCounter++]);
                    }
                    try {
   
   
                        // 等待 3 个线程都打印一遍之后,继续走下一轮的打印
                        cyclicBarrier.await();
                    } catch (InterruptedException e) {
   
   
                        e.printStackTrace();
                    } catch (BrokenBarrierException e) {
   
   
                        e.printStackTrace();
                    }
                }
            }
        };
        // 开启多个线程
        new Thread(runnable).start();
        new Thread(runnable).start();
        new Thread(runnable).start();
    }
}

以上程序执行的结果如下图所示:
image.png

小结

多线程循环打印主要是考察应聘者对于多线程模块掌握的情况,通过应聘者编写的代码和编写代码所用的时间,可以非常直观的了解应聘者的代码基本功。

本文已收录到我的面试小站 www.javacn.site,其中包含的内容有:Redis、JVM、并发、并发、MySQL、Spring、Spring MVC、Spring Boot、Spring Cloud、MyBatis、设计模式、消息队列等模块。


相关文章
|
19天前
|
安全 Java 编译器
深入理解Java中synchronized三种使用方式:助您写出线程安全的代码
`synchronized` 是 Java 中的关键字,用于实现线程同步,确保多个线程互斥访问共享资源。它通过内置的监视器锁机制,防止多个线程同时执行被 `synchronized` 修饰的方法或代码块。`synchronized` 可以修饰非静态方法、静态方法和代码块,分别锁定实例对象、类对象或指定的对象。其底层原理基于 JVM 的指令和对象的监视器,JDK 1.6 后引入了偏向锁、轻量级锁等优化措施,提高了性能。
42 3
|
2月前
|
供应链 安全 NoSQL
PHP 互斥锁:如何确保代码的线程安全?
在多线程和高并发环境中,确保代码段互斥执行至关重要。本文介绍了 PHP 互斥锁库 `wise-locksmith`,它提供多种锁机制(如文件锁、分布式锁等),有效解决线程安全问题,特别适用于电商平台库存管理等场景。通过 Composer 安装后,开发者可以利用该库确保在高并发下数据的一致性和安全性。
43 6
|
6月前
|
安全 Python
告别低效编程!Python线程与进程并发技术详解,让你的代码飞起来!
【7月更文挑战第9天】Python并发编程提升效率:**理解并发与并行,线程借助`threading`模块处理IO密集型任务,受限于GIL;进程用`multiprocessing`实现并行,绕过GIL限制。示例展示线程和进程创建及同步。选择合适模型,注意线程安全,利用多核,优化性能,实现高效并发编程。
83 3
|
5月前
|
Java Windows
【Azure Developer】Windows中通过pslist命令查看到Java进程和线程信息,但为什么和代码中打印出来的进程号不一致呢?
【Azure Developer】Windows中通过pslist命令查看到Java进程和线程信息,但为什么和代码中打印出来的进程号不一致呢?
|
5月前
|
开发者 C# 存储
WPF开发者必读:资源字典应用秘籍,轻松实现样式与模板共享,让你的WPF应用更上一层楼!
【8月更文挑战第31天】在WPF开发中,资源字典是一种强大的工具,用于共享样式、模板、图像等资源,提高了应用的可维护性和可扩展性。本文介绍了资源字典的基础知识、创建方法及最佳实践,并通过示例展示了如何在项目中有效利用资源字典,实现资源的重用和动态绑定。
137 0
|
5月前
|
Java 开发者
解锁Java并发编程的秘密武器!揭秘AQS,让你的代码从此告别‘锁’事烦恼,多线程同步不再是梦!
【8月更文挑战第25天】AbstractQueuedSynchronizer(AQS)是Java并发包中的核心组件,作为多种同步工具类(如ReentrantLock和CountDownLatch等)的基础。AQS通过维护一个表示同步状态的`state`变量和一个FIFO线程等待队列,提供了一种高效灵活的同步机制。它支持独占式和共享式两种资源访问模式。内部使用CLH锁队列管理等待线程,当线程尝试获取已持有的锁时,会被放入队列并阻塞,直至锁被释放。AQS的巧妙设计极大地丰富了Java并发编程的能力。
53 0
|
7月前
|
API
linux---线程互斥锁总结及代码实现
linux---线程互斥锁总结及代码实现
|
7月前
|
Java
【代码诗人】Java线程的生与死:一首关于生命周期的赞歌!
【6月更文挑战第19天】Java线程生命周期,如诗般描绘了从新建到死亡的旅程:创建后待命,`start()`使其就绪,获得CPU则运行,等待资源则阻塞,任务完或中断即死亡。理解生命周期,善用锁、线程池,优雅处理异常,确保程序高效稳定。线程管理,既是艺术,也是技术。
33 3
|
7月前
|
Java
【代码诗人】Java线程的生与死:一首关于生命周期的赞歌!
【6月更文挑战第19天】在Java中,线程经历新建、就绪、运行、阻塞和死亡5个阶段。通过`start()`从新建转为就绪,进而可能运行;阻塞可能因等待资源;完成任务或中断后死亡。管理线程生命周期涉及合理使用锁、线程池、异常处理和优雅关闭,如使用`volatile`和中断标志。了解这些,能提升程序效率和稳定性。
31 2
|
7月前
|
API
Linux---线程读写锁详解及代码实现
Linux---线程读写锁详解及代码实现