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

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

三个线程分别打印字符 abc,每个周期(即一次 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);
            }
        }
    }
}
相关推荐
IT_陈寒8 小时前
闭包陷阱让我加了两天班,JavaScript你真行
前端·人工智能·后端
易协同低代码9 小时前
通达OA核心类库TD类深度解析
后端
Gopher_HBo9 小时前
Go语言学习笔记(十八)Gin处理Session
后端
谭光志10 小时前
工具塞满上下文窗口怎么办?深度拆解 AI Agent Tool Search 按需加载实现原理
前端·后端·ai编程
她说..10 小时前
Java 默认值设置方式
java·开发语言·后端·springboot
foggyprojects10 小时前
从0开始,一句话启动AI DataAgent
后端·数据分析·ai编程
郡杰10 小时前
一些基础和问题解决
后端
陈随易11 小时前
前端项目部署只要30秒
前端·后端·程序员
YIAN11 小时前
从零手写文件读取 MCP 服务:一文吃透 Model Context Protocol 全链路通信原理
前端·后端·mcp
Imchendiana11 小时前
《狂人日记NO.9》— 前后端一把梭,我的全栈实录
前端·后端