并发-常见笔试题-循环打印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();
                }
            }
        }
    }
}
相关推荐
城管不管22 分钟前
第六次面试2026.8.5北京一面已OC
面试·职场和发展
橙子家44 分钟前
使用方法 ToDictionary() 来优化查询时间复杂度:O(N*M) -> O(1*M)【C# 基础】
后端
山荷枝1 小时前
Java学习第十天
java·学习
kyriewen1 小时前
我排查了一个React内存泄漏——罪魁祸首是这3个被忽略的清理函数
前端·javascript·面试
matlabgoodboy1 小时前
计算机毕设代做|Java Python Matlab APP 全套开发设计
java·python·课程设计
IT_陈寒1 小时前
我又被JavaScript的隐式类型转换坑了
前端·人工智能·后端
用户8356290780511 小时前
Python Word 转 PDF 和 PDF 转 Word 指南
后端·python
用户8356290780512 小时前
如何使用 Python 加密和保护 Word 文档
后端·python
他们叫我秃子2 小时前
前端开发转 Go 全栈(五):终于遇到熟人了,Go 的闭包和高阶函数原来这么像 JavaScript
前端·后端·go
SomeB1oody2 小时前
【RustyML入门】2.6. 线性判别分析
开发语言·后端·机器学习·rust·教程