9.线程按序交替
线程按序交替
- 编写一个程序,开启 3 个线程,这三个线程的 ID 分别为 A、B、C,每个线程将自己的 ID 在屏幕上打印 10 遍,要求输出的结果必须按顺序显示。
如:ABCABCABC…… 依次递归解决的思路
在上一章节中,我们学习了 锁 Lock 以及对应的 condition 线程通讯的控制。那么通过一个锁 Lock 可以创建多个 condition ,例如:
- 线程1 使用 condition1 来控制阻塞、唤醒
 - 线程2 使用 condition2 来控制阻塞、唤醒
 - 线程3 使用 condition3 来控制阻塞、唤醒
 
然后我们只要在实现线程类的时候,做好阻塞和唤醒的次序即可。如下:
- 如果当前是线程1,则 调用 condition1.await() 阻塞 线程1,然后调用 condition2.signal() 唤醒 线程2
 - 如果当前是线程2,则 调用 condition2.await() 阻塞 线程2,然后调用 condition3.signal() 唤醒 线程3
 - 如果当前是线程3,则 调用 condition3.await() 阻塞 线程3,然后调用 condition1.signal() 唤醒 线程1
 
好了,下面来实现一下代码。
实现代码
import jdk.nashorn.internal.ir.CallNode;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
/**
 * 编写一个程序,开启 3 个线程,这三个线程的 ID 分别为 A、B、C,
 * 每个线程将自己的 ID 在屏幕上打印 10 遍,要求输出的结果必须按顺序显示。
 * <p>
 * 如:ABCABCABC…… 依次递归
 *
 * @author Aron.li
 * @date 2020/11/3 23:02
 */
public class TestABCAlternate {
    public static void main(String[] args) {
        AlternateDemo ad = new AlternateDemo();
        //创建线程
        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 20; i++) {
                    ad.runThreadA();
                }
            }
        }, "A").start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 20; i++) {
                    ad.runThreadB();
                }
            }
        }, "B").start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 20; i++) {
                    ad.runThreadC();
                }
            }
        }, "C").start();
    }
}
class AlternateDemo {
    //成员属性
    private int number = 1; //标记当前执行的线程
    //创建lock
    private ReentrantLock lock = new ReentrantLock();
    //创建三个线程的 Condition
    private Condition condition1 = lock.newCondition();
    private Condition condition2 = lock.newCondition();
    private Condition condition3 = lock.newCondition();
    //设置后续线程中,执行的方法
    public void runThreadA() {
        //如果当前是线程1,则 调用 condition1.await() 阻塞 线程1,
        // 然后调用 condition2.signal() 唤醒 线程2
        lock.lock();//创建锁
        try {
            //1.判断当前不为线程1,则阻塞线程1
            if (number != 1) {
                condition1.await();
            }
            //2.打印A
            System.out.print(Thread.currentThread().getName());
            //3.唤醒线程2
            number = 2;
            condition2.signal();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock(); // 释放锁
        }
    }
    public void runThreadB() {
        //如果当前是线程2,则 调用 condition2.await() 阻塞 线程2,
        // 然后调用 condition3.signal() 唤醒 线程3
        lock.lock();//创建锁
        try {
            //1.判断当前不为线程2,则阻塞线程2
            if (number != 2) {
                condition2.await();
            }
            //2.打印B
            System.out.print(Thread.currentThread().getName());
            //3.唤醒线程3
            number = 3;
            condition3.signal();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock(); // 释放锁
        }
    }
    public void runThreadC() {
        //如果当前是线程3,则 调用 condition3.await() 阻塞 线程3,
        // 然后调用 condition1.signal() 唤醒 线程1
        lock.lock();//创建锁
        try {
            //1.判断当前不为线程3,则阻塞线程3
            if (number != 3) {
                condition3.await();
            }
            //2.打印C
            System.out.print(Thread.currentThread().getName());
            //3.唤醒线程1
            number = 1;
            condition1.signal();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock(); // 释放锁
        }
    }
}执行效果如下:
 
 
 
 image-20201103233658677










