并发-常见笔试题-循环打印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();
                }
            }
        }
    }
}
相关推荐
无心水5 分钟前
Java时间处理封神篇:java.time全解析
java·开发语言·python·架构·localdate·java.time·java时间处理
wuyikeer9 分钟前
Spring BOOT 启动参数
java·spring boot·后端
多看书少吃饭18 分钟前
Vue + Java + Python 打造企业级 AI 知识库与任务分发系统(RAG架构全解析)
java·vue.js·笔记
studyForMokey31 分钟前
【Android面试】Activity生命周期专题
android·面试·职场和发展
博傅1 小时前
Kubernetes (K8s) 入门到实战教程
java
奋斗的老史1 小时前
Stream-流式操作
java·windows
子木HAPPY阳VIP1 小时前
Ubuntu 22.04 VMware 设置固定IP配置
人工智能·后端·目标检测·机器学习·目标跟踪
人间打气筒(Ada)1 小时前
如何基于 Go-kit 开发 Web 应用:从接口层到业务层再到数据层
开发语言·后端·golang
开心就好20251 小时前
使用Wireshark进行TCP数据包抓包分析:三次握手与四次挥手详解
后端·ios
用户4419395054871 小时前
OpenClaw服务器部署保姆级教程
后端