当前位置: 首页 > news >正文

多线程顺序输出abc

在面试中,如果你能:

  1. 先给出经典的 ReentrantLock + Condition 方案,展示你扎实的基础。

  2. 然后提出单线程池方案,展示你巧妙的工程思维。

  3. 最后再分析 LockSupport 方案,展示你对JUC底层工具的深度理解。

方案1:经典的 ReentrantLock + Condition 

public class ElegantPrintABCWithCondition {

    private final Lock lock = new ReentrantLock();
private final int totalRounds;

private Condition[] conditions = { lock.newCondition(), lock.newCondition(), lock.newCondition() };

// 使用 volatile 保证 state 在多线程间的可见性
private volatile int state = 0;

    public ElegantPrintABCWithCondition(int totalRounds) {
this.totalRounds = totalRounds;
}


public void print(int threadId, char charToPrint) {
for (int i = 0; i < totalRounds; i++) {
lock.lock();
try {
// 使用 while 循环判断,防止虚假唤醒
while (state % 3 != threadId) {
// 等待属于自己的 Condition
conditions[threadId].await();
}

                // 轮到自己,执行打印
System.out.print(charToPrint);

// 状态递增
state++;

                // 按顺序唤醒下一个线程,(threadId + 1) % 3 实现了 0->1, 1->2, 2->0 的循环
conditions[(threadId + 1) % 3].signal();

} catch (InterruptedException e) {
Thread.currentThread().interrupt(); // 保持中断状态
e.printStackTrace();
} finally {
lock.unlock();
}
}
}

    public static void main(String[] args) {
ElegantPrintABCWithCondition printer = new ElegantPrintABCWithCondition(10);

        // 通过 Lambda 表达式为每个线程分配不同的任务
new Thread(() -> printer.print(0, 'A')).start();
new Thread(() -> printer.print(1, 'B')).start();
new Thread(() -> printer.print(2, 'C')).start();
}
}

方案2:单线程池方案

public class ElegantPrintABC {

    public static void main(String[] args) {
// 创建一个单线程的 ExecutorService
ExecutorService executor = Executors.newSingleThreadExecutor();

// 定义打印的总轮数
final int totalRounds = 10;

        for (int i = 0; i < totalRounds; i++) {
// 按顺序提交 A, B, C 三个任务
executor.submit(() -> System.out.print("A"));
executor.submit(() -> System.out.print("B"));
executor.submit(() -> System.out.print("C"));
}

        // 关闭线程池
executor.shutdown();
}
}

方案3 :使用 `LockSupport.park/unpark`——更底层的精准控制

public class ElegantPrintABCWithLockSupport {
static List<Thread> threads = new ArrayList<>();

    public static void main(String[] args) {
final int totalRounds = 10;
char[] chars = {'A', 'B', 'C'};

        for (int i = 0; i < chars.length; i++) {
final int index = i;
Thread t = new Thread(() -> {
for (int j = 0; j < totalRounds; j++) {
// 等待被前一个线程 unpark
LockSupport.park(); 
System.out.print(chars[index]);

// 计算下一个要唤醒的线程的索引
int nextIndex = (index + 1) % threads.size();
// unpark 下一个线程
LockSupport.unpark(threads.get(nextIndex)); 
}
});
threads.add(t);
}

        // 启动所有线程
for (Thread t : threads) {
t.start();
}

        // 启动第一个线程 A
LockSupport.unpark(threads.get(0));
}
}

http://www.dtcms.com/a/419061.html

相关文章:

  • CSS盒模型全面解析
  • 免费开源cms网站源码网页设计公司网站设计
  • [pytest] autouse 参数:自动使用fixture
  • 上海市建上海市建设安全协会网站wordpress盲注
  • 论文阅读三-第二章(3)
  • 在 Windows 系统上怎么使用rabbitmq相关命令,比如:rabbitmqctl list_queues 命令
  • spire.doc for .net 在word的表格最后增加行及索引超限处理办法
  • 【android 驱动开发十】中断唤醒功能-维持500ms唤醒状态
  • 微信上可以做网站吗广州专业视频制作
  • wordpress还原网站源码易语言 wordpress
  • 深入解析AppCrawler:开源自动遍历测试工具配置指南
  • 24届(华为OD)Java面经
  • 20届-测试面经-华为OD
  • 重庆seo整站优化效果百度竞价推广属于什么广告
  • 朝阳区住房和城乡建设部网站营销模式有几种
  • linux学习笔记(5)计算机基本硬件结构
  • 自定义分页控件,只显示当前页码的前后N页
  • 软件开发和网站建设的区别做车贷的网站
  • PC16550串口中断接收与异常处理程序
  • 自动化脚本提升效率
  • mysql旧版本存储嵌入模型的向量数据
  • 公司网站建设宣传话语申请一个域名可以建设一个网站吗
  • 合川做网站临汾网站建设
  • HGAME 2023 week1]a_cup_of_tea
  • vue 打包element plus组件生成对应css文件的问题
  • 网站 接入微信公众号登陆入口
  • 做网站和做appwordpress category模板
  • Windows---进程状态信息获取的核心接口<Psapi.h>
  • flink状态管理
  • 有成功案例的网站汉口北做网站