并发-常见笔试题-循环打印ABC

本文主要列举常见并发编程笔试题,以便能够熟练使用常见并发编程

题目一:三个线程循环打印abc,共打印100次

解法1:lock.condition和countdownlatch

思路一个volatile变量num记录打印次数,lock对象new3个condition对象c1 c2 c3,每次打印时一个对象等待,打印后另一个对象唤醒,相互循环

代码如下:

java 复制代码
private static volatile int num = 100;

@Test
public void testCase() throws InterruptedException {
    ReentrantLock lock = new ReentrantLock();
    Condition c1 = lock.newCondition();
    Condition c2 = lock.newCondition();
    Condition c3 = lock.newCondition();
    CountDownLatch countDownLatch = new CountDownLatch(3);
    new Thread(new PrintTask(lock, c1, c2, 'a', countDownLatch)).start();
    new Thread(new PrintTask(lock, c2, c3, 'b', countDownLatch)).start();
    new Thread(new PrintTask(lock, c3, c1, 'c', countDownLatch)).start();
    countDownLatch.await();
    lock.lock();
    try {
        c1.signalAll();
    } finally {
        lock.unlock();
    }
    while (num > 0) {
        LockSupport.parkNanos(1000L);
    }
}

private static class PrintTask implements Runnable {
    private Condition c1;
    private Condition c2;
    private Lock lock;
    private char ch;
    private CountDownLatch countDownLatch;

    public PrintTask(Lock lock, Condition c1, Condition c2, char ch, CountDownLatch countDownLatch) {
        this.c1 = c1;
        this.c2 = c2;
        this.ch = ch;
        this.lock = lock;
        this.countDownLatch = countDownLatch;
    }

    @Override
    public void run() {
        countDownLatch.countDown();
        while (num > 0) {
            lock.lock();
            try {
                c1.await();
                if (num > 0) {
                    System.out.println(ch);
                    num--;
                }
                c2.signal();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    }
}

解法2:使用三个信号量semaphore来解

思路同解法1

java 复制代码
private static volatile int num = 100;

@Test
public void testCase() {
    Semaphore semaphoreA = new Semaphore(1);
    Semaphore semaphoreB = new Semaphore(0);
    Semaphore semaphoreC = new Semaphore(0);

    Thread threadA = new Thread(new PrintTask('a', semaphoreA, semaphoreB));
    Thread threadB = new Thread(new PrintTask('b', semaphoreB, semaphoreC));
    Thread threadC = new Thread(new PrintTask('c', semaphoreC, semaphoreA));

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

private static class PrintTask implements Runnable {
    private char character;
    private Semaphore currentSemaphore;
    private Semaphore nextSemaphore;

    public PrintTask(char character, Semaphore currentSemaphore, Semaphore nextSemaphore) {
        this.character = character;
        this.currentSemaphore = currentSemaphore;
        this.nextSemaphore = nextSemaphore;
    }

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            try {
                currentSemaphore.acquire();
                if (num > 0) {
                    System.out.println(character);
                    num--;
                }
                nextSemaphore.release();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

解法3:使用Object,条件性判断是否需要wait

代码如下:

java 复制代码
private static final Object lock = new Object();
private static volatile int count = 0;

@Test
public void testCase() {
    Thread threadA = new Thread(new PrintTask('A', 0));
    Thread threadB = new Thread(new PrintTask('B', 1));
    Thread threadC = new Thread(new PrintTask('C', 2));

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

private static class PrintTask implements Runnable {
    private char character;
    private int targetCount;

    public PrintTask(char character, int targetCount) {
        this.character = character;
        this.targetCount = targetCount;
    }

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            synchronized (lock) {
                try {
                    while (count % 3 != targetCount) {
                        lock.wait();
                    }
                    System.out.println(character);
                    count++;
                    lock.notifyAll();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
相关推荐
leeyi8 小时前
Agent 要用 API key,但明文一次都不能进模型——Secret Runtime 落地实录(第110篇)
后端·aigc·agent
GreenTea8 小时前
发布 3 天登顶 HN:不生成一个字的模型 Jev,我把它的源码和黑料都扒了一遍
前端·后端·算法
JoyT8 小时前
Spring AI 2.0 RAG 工程优化:从 Chunking、混合检索到 Rerank
后端
她的男孩8 小时前
做了"异步导出",用户点了还是卡 3 分钟:扒完 4223 行源码,@Async 压根没生效
人工智能·后端·程序员
白远山9 小时前
本地游戏代练源码开发实战:架构设计与核心功能实现指南
java·开发语言·架构·需求分析
wno7049 小时前
Spring Security添加图形验证码
java·后端·spring
曹牧9 小时前
Postman:`Content-Type` 和 `charset`
java
逆境不可逃9 小时前
Pi Agent 学习笔记:扩展如何介入工具调用
java
ewbok9 小时前
Springboot整合mqtt实现软硬件通信
后端
CRZZX9 小时前
阶段 0.3:为 AI Agent 建立输入、工具、限流与前端渲染安全边界
后端