【推荐】开启三个线程打印ABC-ReentrantLock+Condition

2022-3-8 diaba 多线程

package com.jiucaiyuan.net.thread;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * <p>
 * 题目:
 * 编写程序,开启三个线程,这三个线程的ID分别是A,B,C,每个线程将自己的ID在屏幕上打印十次,
 * 要求输出结果必须按照ABC的顺序显示,如:ABCABCABC...
 *
 * 指定线程唤醒轮循打印,使用ReentrantLock和Condition。 本方法空间开销较大,因为使用了三个条件对象,
 * 但是本方法是定点唤醒线程,并不会产生额外的上下文切换开销。总体来说,本方法性能更优。
 *
 * </p>
 */
class RotationPrint implements Runnable {
    private static volatile String whoCanPrint;
    private String whoPrintFollow;
    private int printTime;
    private ReentrantLock reentrantLock;
    private Condition myCondition;
    private Condition nextCondition;

    public RotationPrint(ReentrantLock lock, Condition myCondition, Condition nextCondition, String nextName) {
        this.printTime = 0;
        this.reentrantLock = lock;
        this.myCondition = myCondition;
        this.nextCondition = nextCondition;
        this.whoPrintFollow = nextName;
    }

    public static void setWhoCanPrint(String s) {
        whoCanPrint = s;
    }

    @Override
    public void run() {
        while (printTime++ < 10) {
            try {
                reentrantLock.lock();
                //判断当前线程是否是需要打印的线程。
                while (Thread.currentThread().getName() != whoCanPrint) {
                    try {
                        myCondition.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                //System.out.println("线程" + Thread.currentThread().getName() + "   第" + printTimes + "次打印");
                System.out.print(Thread.currentThread().getName());
                whoCanPrint = whoPrintFollow;
                //指定唤醒下一个需要打印的线程。
                nextCondition.signal();
            } finally {
                reentrantLock.unlock();
            }
        }    

    }
    public static void main(String[] args) {
        ReentrantLock lock = new ReentrantLock();
        Condition aCondition = lock.newCondition();
        Condition bCondition = lock.newCondition();
        Condition cCondition = lock.newCondition();
        //设置第一个需要打印的线程
        RotationPrint.setWhoCanPrint("A");
        new Thread(new RotationPrint(lock, aCondition, bCondition, "B"), "A").start();
        new Thread(new RotationPrint(lock, bCondition, cCondition, "C"), "B").start();
        new Thread(new RotationPrint(lock, cCondition, aCondition, "A"), "C").start();
    }
}

发表评论:

Powered by emlog 京ICP备15045175号-1 Copyright © 2022