三个线程交替打印的几种实现方式

本文介绍了四种Java中实现线程间交替打印的方法:synchronized+wait/notify、ReentrantLock+Condition、Semaphore信号量以及AtomicInteger的CAS操作,展示了不同技术在并发控制中的应用。
摘要由CSDN通过智能技术生成

前言

线程的交替打印,实际上涉及的内容是线程间的通信,下面,介绍三种线程间通信实现的交替打印方法和一种非线程间通信的实现方式。

线程通信方式

1、synchronized + wait&notify/notifyAll

synchronized是Java中的一个关键字,用于实现对共享资源的互斥访问。wait和notify/notifyAll是Object类中的两个方法,用于实现线程间的通信。wait方法会让当前线程释放锁,并进入等待状态,直到被其他线程唤醒。notify/notifyAll方法会唤醒一个在同一个锁上等待的线程。我们可以使用一个共享变量a来表示当前应该打印哪个字母,初始值为0。当state为0时,表示轮到A线程打印;当a为1时,表示轮到B线程打印;当a为2时,表示轮到C线程打印。每个线程在打印完字母后,需要将a设置为下一个线程的值,以便循环。同时,每个线程还需要唤醒下一个线程,并让自己进入等待状态。

static class m1{
        private static int a = 0;
        private final static Object lock = new Object();

        public void test(){
            new Thread(()->{
                synchronized(lock){
                    while(a != 0){
                        try {
                            lock.wait();
                        } catch (Exception e) {
                            throw new RuntimeException(e);
                        }
                    }
                    System.out.println(Thread.currentThread().getName());
                    a = 1;
                    lock.notifyAll();
                }
            },"AAAAAAAAAAAAAA").start();

            new Thread(()->{
                synchronized(lock){
                    while(a != 1){
                        try {
                            lock.wait();
                        } catch (InterruptedException e) {
                            throw new RuntimeException(e);
                        }
                    }
                    System.out.println(Thread.currentThread().getName());
                    a = 2;
                    lock.notifyAll();
                }
            },"BBBBBBBBBBBBBB").start();

            new Thread(()->{
                synchronized(lock){
                    while(a != 2){
                        try {
                            lock.wait();
                        } catch (InterruptedException e) {
                            throw new RuntimeException(e);
                        }
                    }
                    System.out.println(Thread.currentThread().getName());
                    a = 0;
                    lock.notifyAll();
                }
            },"CCCCCCCCCCCCCC").start();
        }
    }
2、reentrantLock + condition条件

ReentrantLock是Java中的一个类,用于实现可重入的互斥锁,是AQS的一种实现。ConditionReentrantLock中的一个接口,用于实现线程间的条件等待和唤醒。ReentrantLock可以创建多个Condition对象,每个Condition对象可以绑定一个或多个线程,实现对不同线程的精确控制。我们可以使用一个ReentrantLock对象作为锁,同时创建三个Condition对象,分别绑定A、B、C三个线程。每个线程在打印字母之前,需要调用对应的Condition对象的await方法,等待被唤醒。每个线程在打印字母之后,需要调用下一个Condition对象的signal方法,唤醒下一个线程。

static class m2{
        private static int state = 0;
        private final static ReentrantLock lock = new ReentrantLock();

        private final static Condition A = lock.newCondition();
        private final static Condition B = lock.newCondition();
        private final static Condition C = lock.newCondition();

        public void test(){
            new Thread(()->{
                lock.lock();
                try{
                    while(state != 0){
                        A.await();
                    }
                    System.out.println(Thread.currentThread().getName());
                    state = 1;
                    B.signal();
                }catch (Exception e){
                    e.printStackTrace();
                }finally {
                    lock.unlock();
                }
            },"AAAAAAAAAAAAAA").start();

            new Thread(()->{
                lock.lock();
                try{
                    while(state != 1){
                        B.await();
                    }
                    System.out.println(Thread.currentThread().getName());
                    state = 2;
                    C.signal();
                }catch (Exception e){
                    e.printStackTrace();
                }finally {
                    lock.unlock();
                }
            },"BBBBBBBBBBBBBB").start();

            new Thread(()->{
                lock.lock();
                try{
                    while(state != 2){
                        C.await();
                    }
                    System.out.println(Thread.currentThread().getName());
                    state = 0;
                    A.signal();
                }catch (Exception e){
                    e.printStackTrace();
                }finally {
                    lock.unlock();
                }
            },"CCCCCCCCCCCCCC").start();
        }
    }
3、Semaphore信号量

Semaphore是Java中的一个类,用于实现信号量机制。信号量是一种计数器,用于控制对共享资源的访问。Semaphore可以创建多个信号量对象,每个信号量对象可以绑定一个或多个线程,实现对不同线程的精确控制。我们可以使用三个Semaphore对象,分别初始化为1、0、0,表示A、B、C三个线程的初始许可数。每个线程在打印字母之前,需要调用对应的Semaphore对象的acquire方法,获取许可。每个线程在打印字母之后,需要调用下一个Semaphore对象的release方法,释放许可。

static class m3{
        private static final Semaphore A = new Semaphore(1);
        private static final Semaphore B = new Semaphore(0);
        private static final Semaphore C = new Semaphore(0);

        public static void test(){
            new Thread(()->{
                try{
                    A.acquire();
                    System.out.println(Thread.currentThread().getName());
                    B.release();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            },"AAAAAAAAAAAAAA").start();

            new Thread(()->{
                try{
                    B.acquire();
                    System.out.println(Thread.currentThread().getName());
                    C.release();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            },"BBBBBBBBBBBBBB").start();

            new Thread(()->{
                try{
                    C.acquire();
                    System.out.println(Thread.currentThread().getName());
                    A.release();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            },"CCCCCCCCCCCCCC").start();
        }
    }

非线程通信方式

通过cas操作

AtomicInteger是Java中的一个类,用于实现原子性的整数操作。CAS是一种无锁的算法,全称为Compare And Swap,即比较并交换。CAS操作需要三个参数:一个内存地址,一个期望值,一个新值。如果内存地址的值与期望值相等,就将其更新为新值,否则不做任何操作。我们可以使用一个AtomicInteger对象来表示当前应该打印哪个字母,初始值为0。当state为0时,表示轮到A线程打印;当state为1时,表示轮到B线程打印;当state为2时,表示轮到C线程打印。每个线程在打印完字母后,需要使用CAS操作将state设置为下一个线程值,以便循环。

public static class m4{
        private static volatile AtomicInteger state = new AtomicInteger(0);

        public void test(){
            new Thread(()->{
                while(state.get() == 0){
                    System.out.println(Thread.currentThread().getName());
                    state.compareAndSet(state.get(), 1);
                }
            },"AAAAAAAAAAAAAA").start();

            new Thread(()->{
                while(state.get() == 1){
                    System.out.println(Thread.currentThread().getName());
                    state.compareAndSet(state.get(), 2);
                }
            },"BBBBBBBBBBBBBB").start();

            new Thread(()->{
                while(state.get() == 2){
                    System.out.println(Thread.currentThread().getName());
                    state.compareAndSet(state.get(), 0);
                }
            },"CCCCCCCCCCCCCC").start();
        }

    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

雅俗共赏zyyyyyy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值