多线程循环输出abc问题

本文分享了三种不同的方法来解决一个编程问题:在Java中使用wait(),notifyAll()、ReentrantLock的await()和signal()以及LockSupport的park()和unpark(),实现三个线程按顺序循环输出a,b,c。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        大家好,我是程序员阿药。今天和大家分享的是我遇到过的一个多线程问题,感觉挺有意思的,希望各位小伙伴喜欢。

问题描述:

        给定三个线程t1、t2、t3;t1输出a,t2输出b,t3输出c;然后再由t1输出a,t2输出b。。。以此循环输出5次。

        最终结果:abcabcabcabcabc。

话不多说,开码!

方式一:

使用wait()和notifyAll()实现

public static void testWaitAndNotify() {
    WaitNotify waitNotify = new WaitNotify(1, 5);
    new Thread(() -> {
        waitNotify.print("a", 1, 2);
    }, "t1").start();
    new Thread(() -> {
        waitNotify.print("b", 2, 3);
    }, "t2").start();
    new Thread(() -> {
        waitNotify.print("c", 3, 1);
    }, "t3").start();
}

/**
 * 输出内容     等待标记    下一个标记
 * a            1           2
 * b            2           3
 * c            3           1
 */
public void print(String content, int waitFlag, int nextFlag) {
    for (int i = 0; i < loop; i++) {
        synchronized (this) {
            // 判断当前线程的等待标记和待打印标记是否一致
            while (waitFlag != this.flag) {
                try {
                    // 不一致则等待
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            // 一致则打印
            System.out.print(content);
            // 修改待打印标记,置为一下次要打印的标记
            this.flag = nextFlag;
            // 通知其他线程打印
            this.notifyAll();
        }
    }
}

方式二:

使用ReentrantLock中的await()和signal()实现

public static void testAwaitAndSignal() {
    // 创建锁
    AwaitSignal awaitSignal = new AwaitSignal(5);
    // 用这把锁创建三个休息室
    Condition condition = awaitSignal.newCondition();
    Condition condition1 = awaitSignal.newCondition();
    Condition condition2 = awaitSignal.newCondition();
    // 创建三个打印线程
    new Thread(() -> {
        awaitSignal.print("a", condition, condition1);
    }, "t1").start();
    new Thread(() -> {
        awaitSignal.print("b", condition1, condition2);
    }, "t2").start();
    new Thread(() -> {
        awaitSignal.print("c", condition2, condition);
    }, "t3").start();
    // 上面三个线程启动,但是都在等待,所以需要被唤醒
    try {
        Thread.sleep(1000);
        // 主线程得到锁
        awaitSignal.lock();
        System.out.println("running start");
        // 主线程先唤醒第一个线程
        condition.signal();
    } catch (InterruptedException e) {
        e.printStackTrace();
    } finally {
        awaitSignal.unlock();
    }
}

public void print(String content, Condition cur, Condition next) {
    for (int i = 0; i < loop; i++) {
        // 上锁
        lock();
        try {
            // 当前线程进入等待
            cur.await();
            // 当前线程被唤醒后,执行打印
            System.out.print(content);
            // 唤醒下一个线程
            next.signal();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            // 释放锁
            unlock();
        }
    }
}

方式三:

使用LockSupport中的park()和unpark()实现

public static void testParkAndUnpark() {
    ParkUnPark parkUnPark = new ParkUnPark(5);
    t1 = new Thread(() -> {
        parkUnPark.print("a", t2);
    }, "t1");
    t2 = new Thread(() -> {
        parkUnPark.print("b", t3);
    }, "t2");
    t3 = new Thread(() -> {
        parkUnPark.print("c", t1);
    }, "t3");
    t1.start();
    t2.start();
    t3.start();
    System.out.println("running start");
    LockSupport.unpark(t1);
}

public void print(String content, Thread next) {
    for (int i = 0; i < loop; i++) {
        LockSupport.park();
        System.out.print(content);
        LockSupport.unpark(next);
    }
}

        大家如果有其它的实现方式可以在评论区互相交流哦。喜欢的小伙伴可以点赞、收藏支持一下!

        需要完整源码的小伙伴可以关注我的微信公众号:“程序员阿药”,回复 “abc问题” 即可获得完整源码。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值