三种方式来实现多线程连续打印abc

最近面试的时候会遇到这样的问题,竟然没有写出来,还是自己多练习吧 需求是这样的:

三个线程分别打印字符 a、b、c,每个周期(即一次 abc)打印完成后换行

如果是让连续a b c 分开换行 只需要更改print的逻辑即可,不用在区分abc了

Synchronized

java 复制代码
package com.example.test;

public class Thread13 {
    private static final Object lock = new Object();
    private static int turn = 0; // 新增共享变量,记录当前该执行的线程编号

    public static void main(String[] args) {
        // 复用 print 方法创建线程
        Thread thread1 = new Thread(() -> print('a', 0));
        Thread thread2 = new Thread(() -> print('b', 1));
        Thread thread3 = new Thread(() -> print('c', 2));
        thread1.start();
        thread2.start();
        thread3.start();
    }

    // 合并后的打印方法
    public static void print(char c, int n) {
        for (int i = 0; i < 10; i++) {
            synchronized (lock) {
                // 使用 while 循环,确保线程被唤醒后再次检查条件
                while (turn != n) {
                    try {
                        lock.wait();
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                    }
                }
                if (c == 'c') {
                    System.out.println(c);
                } else {
                    System.out.print(c);
                }
                turn = (turn + 1) % 3; // 更新 turn 变量,让下一个线程执行
                lock.notifyAll();
            }
        }
    }
}

ReentrantLock 和 Condition

java 复制代码
package com.example.test;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class thread14 {
    private static final int TOTAL_ITERATIONS = 10;
    private static final Lock lock = new ReentrantLock();
    private static final Condition conditionA = lock.newCondition();
    private static final Condition conditionB = lock.newCondition();
    private static final Condition conditionC = lock.newCondition();
    private static char current = 'a';

    public static void main(String[] args) {
        Thread threadA = new Thread(() -> printChar('a', conditionA, conditionB, 'b'));
        Thread threadB = new Thread(() -> printChar('b', conditionB, conditionC, 'c'));
        Thread threadC = new Thread(() -> printChar('c', conditionC, conditionA, 'a'));

        threadA.start();
        threadB.start();
        threadC.start();

        // 等待所有线程完成
        try {
            threadA.join();
            threadB.join();
            threadC.join();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new RuntimeException(e);
        }

        System.out.println("\n所有线程打印完成!");
    }

    private static void printChar(char character, Condition currentCondition, Condition nextCondition, char nextCharacter) {
        for (int i = 0; i < TOTAL_ITERATIONS; i++) {
            lock.lock();
            try {
                while (current != character) {
                    currentCondition.await();
                }
                System.out.print(character);
                // 判断是否是第三个线程打印后换行
                if (character == 'c') {
                    System.out.println();
                }
                current = nextCharacter;
                nextCondition.signal();
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                throw new RuntimeException(e);
            } finally {
                lock.unlock();
            }
        }
    }
}

Semaphore

java 复制代码
package com.example.test;

import java.util.concurrent.Semaphore;

public class thread15 {
    private static final int TOTAL_ITERATIONS = 10;
    private static Semaphore semaphoreA = new Semaphore(1);
    private static Semaphore semaphoreB = new Semaphore(0);
    private static Semaphore semaphoreC = new Semaphore(0);

    public static void main(String[] args) {
        Thread threadA = new Thread(() -> printChar('a', semaphoreA, semaphoreB));
        Thread threadB = new Thread(() -> printChar('b', semaphoreB, semaphoreC));
        Thread threadC = new Thread(() -> printChar('c', semaphoreC, semaphoreA));

        threadA.start();
        threadB.start();
        threadC.start();

        // 等待所有线程完成
        try {
            threadA.join();
            threadB.join();
            threadC.join();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new RuntimeException(e);
        }

        System.out.println("\n所有线程打印完成!");
    }

    private static void printChar(char character, Semaphore currentSemaphore, Semaphore nextSemaphore) {
        for (int i = 0; i < TOTAL_ITERATIONS; i++) {
            try {
                currentSemaphore.acquire();
                System.out.print(character);
                // 判断是否是第三个线程打印后换行
                if (character == 'c') {
                    System.out.println();
                }
                nextSemaphore.release();
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                throw new RuntimeException(e);
            }
        }
    }
}
相关推荐
颜进强43 分钟前
16 · NestJS LifecycleEvents 生命周期事件:五个钩子、三条边界,和 rag-server 的优雅停机
前端·后端·ai编程
GetcharZp1 小时前
定位不再一个个吐坐标:英伟达 LocateAnything 上手全攻略
后端
郑州光合科技余经理2 小时前
同城电商系统:库存变更怎么同步到订单
java·开发语言·前端·后端·uni-app·php·ai编程
我叫黑大帅2 小时前
Go日志库工程选型与逃逸分析评测报告
后端·面试·go
IT_陈寒5 小时前
JavaScript闭包的这个坑,我居然今天才爬出来
前端·人工智能·后端
Thneonl5 小时前
消息队列选型决策树:RabbitMQ vs Kafka vs Redis Streams
后端·架构
晚安日记wanna5 小时前
大厂禁 JOIN 的真正原因,拆到第四层才清楚
数据库·后端·面试
dd聊技术5 小时前
LLM 说"你这篇和已有文章 92% 相似",我去查了——它编的
后端
行百里er6 小时前
Redis 持久化——RDB 快照 vs AOF 日志
redis·后端