并发-常见笔试题-循环打印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();
                }
            }
        }
    }
}
相关推荐
牛奔4 小时前
Go 如何避免频繁抢占?
开发语言·后端·golang
寻星探路8 小时前
【深度长文】万字攻克网络原理:从 HTTP 报文解构到 HTTPS 终极加密逻辑
java·开发语言·网络·python·http·ai·https
想用offer打牌9 小时前
MCP (Model Context Protocol) 技术理解 - 第二篇
后端·aigc·mcp
曹牧10 小时前
Spring Boot:如何测试Java Controller中的POST请求?
java·开发语言
KYGALYX10 小时前
服务异步通信
开发语言·后端·微服务·ruby
掘了10 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
爬山算法11 小时前
Hibernate(90)如何在故障注入测试中使用Hibernate?
java·后端·hibernate
kfyty72511 小时前
集成 spring-ai 2.x 实践中遇到的一些问题及解决方案
java·人工智能·spring-ai
猫头虎11 小时前
如何排查并解决项目启动时报错Error encountered while processing: java.io.IOException: closed 的问题
java·开发语言·jvm·spring boot·python·开源·maven