9.线程按序交替

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(); // 释放锁
        }
    }

}

执行效果如下:

9.线程按序交替
image-20201103233658677


原文始发于微信公众号(海洋的渔夫):9.线程按序交替

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/34950.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!