三种方式来实现多线程连续打印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);
            }
        }
    }
}
相关推荐
打工仔折腾 AI1 小时前
网易UU远程实测:手机控电脑做Python开发和Agent调试的真实体验
人工智能·后端·python·智能手机·性能优化·电脑·ai agent 实战
YYYing.2 小时前
【设计模式系列 (四) 】建造者模式
c++·后端·设计模式·建造者模式·c/c++
IT_陈寒2 小时前
用Vue时这个响应式陷阱坑了我一整天
前端·人工智能·后端
孙启超2 小时前
【AI开发之Rust】第 20 课:壳侧 API 封装 —— 把 Rust 能力接进真实 UI
开发语言·后端·rust
BingoGo2 小时前
用 Jev 与 Laravel AI SDK 检测垃圾邮件和自动回复
后端·laravel
JaguarJack2 小时前
用 Jev 与 Laravel AI SDK 检测垃圾邮件和自动回复
后端·ai·php·laravel·服务端
mldong2 小时前
同一套充血模型,八种语言八种长相
后端·架构
噢,我明白了10 小时前
java中唯一键和幂等键的应用
java·后端
GreenTea10 小时前
我把 Agent 的 while 循环拆掉了:一种你可能没想到的 Agent 架构
前端·后端·架构
考虑考虑10 小时前
synchronized字符串常量
java·后端·java ee