并发-常见笔试题-循环打印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();
                }
            }
        }
    }
}
相关推荐
睆小白3 分钟前
【springboot】实现文件上传和下载
java·spring boot·后端
ChinaRainbowSea8 分钟前
十六,Spring Boot 整合 Druid 以及使用 Druid 监控功能
java·spring boot·后端·spring·web
吴半杯20 分钟前
Mysql调优之性能监控(一)
java·linux·mysql
.生产的驴36 分钟前
Docker 消息队列RabbitMQ 安装延迟消息插件
运维·spring boot·后端·docker·容器·rabbitmq·java-rabbitmq
慢慢雨夜1 小时前
uniapp 苹果安全域适配
java·前端·uni-app
mit6.8241 小时前
[Linux#49][UDP] 2w字详解 | socketaddr | 常用API | 实操:实现简易Udp传输
linux·网络·c++·笔记·后端
敲代码不忘补水1 小时前
二十种编程语言庆祝中秋节
java·javascript·python·golang·html
码农研究僧1 小时前
Java或者前端 实现中文排序(调API的Demo)
java·前端·localecompare·中文排序·collator
Chase-Hart1 小时前
【每日一题】LeetCode 7.整数反转(数学)
java·数据结构·算法·leetcode·eclipse
四角小裤儿儿1 小时前
Java数据结构(十一)——归并排序、计数排序
java·数据结构·排序算法