首页 > 其他分享 >蔚来手撕代码题:三个线程循环打印ABC

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

时间:2023-06-25 09:11:43浏览次数:47  
标签:ABC sharedCounter 蔚来 打印 循环 线程 new CyclicBarrier

问题如下:
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、设计模式、消息队列等模块。

标签:ABC,sharedCounter,蔚来,打印,循环,线程,new,CyclicBarrier
From: https://www.cnblogs.com/vipstone/p/17502106.html

相关文章

  • [ABC259F] Select Edges 题解
    Solution考虑树形\(dp\)。我们可以注意到节点\(i\)的相邻的边中被选中的不超过\(d_i\)条,显然我们可以定义状态\(dp_{u,k}\)表示节点\(u\)连接子节点的边有\(k\)条的最大值。但是此处没有给定\(d_i\)的范围,所以对于一个节点最多可能会有\(n-1\)个点,所以时间复杂......
  • AtCoder Beginner Contest(abc) 299
    A-TreasureChest题目大意给定一个由'|''*'和'.'组成的字符串,并且保证一定有1个'*'和2个'|',检查'*'是否在两个'|'之间;解题思路签到题不多嗦了;但是这里可以注意一下string的find函数;find(charc,intpos)意为从第pos个字符开始找字符c,返回值......
  • 使用了并发工具类库,线程安全就高枕无忧了吗?
    1、说明在代码审核讨论的时候,我们有时会听到有关线程安全和并发工具的一些片面的观点和结论,比如“把HashMap改为ConcurrentHashMap,就可以解决并发问题了呀”,“要不我们试试无锁的CopyOnWriteArrayList吧,性能更好”。事实上,这些说法都不太准确。的确,为了方便开发者进行多线程编......
  • [C/C++] Visual Stdio Code中多线程多源码文件编译、运行和调试
    搞了很久,记录一下:一.环境OS:Ubuntu20.04VSCode:1.77.0g++:g++(Ubuntu9.4.0-1ubuntu1~20.04.1)9.4.0二.配置文件下面两个文件先不要手动创建,下面第三章会讲到:task.json:编译程序的配置文件;launch.json:运行程序的配置文件.三.编译&运行1.打开main函数所在的cpp文......
  • 【题解】AtCoder-ABC306G Return to 1
    这也太强了!容易想到的是用若干环拼出这个\(10^{10^{100}}\),也就是这些环的\(\gcd\mid10\)。之后就不会了。先正图反图两次DFS,只留下\(1\)所在强连通分量里的边,对正图跑DFS生成树,定义其深度从\(0\)开始,然后有一个结论是:对于任何正整数\(a\),图中存在一个包含\(1\)......
  • abc059d <博弈, 打表找规律>
    D-Alice&Brown如何打表要善于通过打表展示视觉信息,从而找到规律;#include<iostream>#include<algorithm>usingnamespacestd;typedeflonglongLL;intf[100][100];//0未定,1win,2lose//注意这里找先手必胜与必负的方式//当我的可以转移到任何一个必输态......
  • abc058d <公式化简>
    D-###原计算公式为:\[\sum\limits_{1\lei<j\len}\sum\limits_{1\lek<l\lem}(x_j-x_i)(y_l-y_k)\]可将xy拆分:\[\left(\sum\limits_{1\leqi<j\leqn}(x_j-x_i)\right)\left(\sum\limits_{1\leqk<l\leqm}(y_l-y_k)\right)\]仅计算x侧可进一步化简......
  • CPU核数和线程数有什么作用?
    我们在选择服务器配置的时候,CPU的性能也是咱们需要考虑的一点,除了考虑架构、工艺、单核性能等,还需要考虑核心数和线程数量,CPU从早期的单核,发展到现在的双核、多核,除了核心数量之外,还有线程数量也是越来越多那么CPU核数和线程数有什么作用?CPU核数和线程数什么意思?今天我给大家分享CP......
  • Thread类中的常用线程调度方法sleep、yield、join
    sleepsleep方法是在Thread类中的一个静态方法,当一个线程调用了sleep方法,被调用的那个线程就会暂时的让出指定时间的CPU执行权,在这段时间也不会参与CPU的调度,当时间到了之后,就会重新回到就绪状态,等待CPU的再次调度,注意是就绪状态,而不是重新拿回CPU的执行权。并且,在休眠期间,只是会......
  • java线程的五种状态
    五种状态开始状态(new)就绪状态(runnable)运行状态(running)阻塞状态(blocked)结束状态(dead)状态变化1、线程刚创建时,是new状态2、线程调用了start()方法后,进入runnable状态,此时并未真正执行,需要和其他线程竞争cpu资源3、当该线程竞争到了cpu资源,进入running状态4、线程因为某种......