Skip to content

线程A、B、C分别打印1,2,3顺序执行10次

题目

线程A,B,C分别打印1,2,3; 并顺序执行10次;

解法一

基本思路

  1. 即根据题目意思, 要求使用三个线程分别命名为A, B, C; 并且线程A打印1, 线程B打印2, 线程C打印3, 按顺序执行10次;
  2. 可以利用 Semaphore 信号量实现, 利用 acquire() 方法, 若不满足访问共享资源条件则会令当前线程阻塞; 和 release() 方法, 释放资源, 并唤醒等待资源的线程;

实现代码

java
public class ThreeThreadsPrint123 {

    public static void main(String[] args) {
        // 信号量 控制访问资源的线程数量 设置线程数为0
        Semaphore first = new Semaphore(0);
        Semaphore second = new Semaphore(0);
        Semaphore third = new Semaphore(0);

        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 10; ++ i) {
                try {
                    // 线程 A 打印 1
                    System.out.println("线程: " + Thread.currentThread().getName() + "打印: 1");
                    // 休眠一秒 便于观察结果
                    Thread.sleep(1000);
                    // release 会释放信号量 并唤醒等待线程
                    second.release();
                    // 尝试访问资源 因为允许0个线程访问 所以会阻塞线程 A
                    first.acquire();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        }, "A");
        Thread t2 = new Thread(() -> {
            for (int i = 0; i < 10; ++ i) {
                try {
                    // 先阻塞线程B 保证线程A先打印结束后 再唤醒线程B
                    second.acquire();
                    // 线程 B 打印 2
                    System.out.println("线程: " + Thread.currentThread().getName() + "打印: 2");
                    // 休眠一秒 便于观察结果
                    Thread.sleep(1000);
                    // release 会释放信号量 并唤醒等待线程
                    third.release();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        }, "B");
        Thread t3 = new Thread(() -> {
            for (int i = 0; i < 10; ++ i) {
                try {
                    // 先阻塞线程C 保证线程B先打印结束后 再唤醒线程C
                    third.acquire();
                    // 线程 C 打印 3
                    System.out.println("线程: " + Thread.currentThread().getName() + "打印: 3");
                    // 休眠一秒 便于观察结果
                    Thread.sleep(1000);
                    // release 会释放信号量 并唤醒等待线程
                    first.release();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        }, "C");

        t1.start();
        t2.start();
        t3.start();

    }

}

解法二

基本思路

  1. 使用 synchronized 同步锁来实现, 使用 wait() 方法来让线程等待, 使用 notifyAll() 方法来唤醒线程

实现代码

java
public class ThreeThreadsPrint123_2 {

    // 计数器:计算当前打印次数
    private int count = 0;
    // 同步锁对象
    private final Object lock = new Object();

    // 打印方法:0打印A,1打印B,2打印C
    public void printNum(int flag) {
        for (int i = 0; i < 10; ++ i) {
            synchronized (lock) {
                while (count % 3 != flag && count < 30) {
                    try {
                        // 若没有轮到当前线程打印 则让当前线程等待
                        lock.wait();
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
                if (count < 30) {
                    System.out.println("线程: " + Thread.currentThread().getName() + " 打印: " + (1 + flag));
                    // 次数增加
                    ++ count;
                    // 唤醒所有线程
                    lock.notifyAll();
                }
            }
        }
    }

    public static void main(String[] args) {
        ThreeThreadsPrint123_2 obj = new ThreeThreadsPrint123_2();
        Thread t1 = new Thread(() -> obj.printNum(0), "A");
        Thread t2 = new Thread(() -> obj.printNum(1), "B");
        Thread t3 = new Thread(() -> obj.printNum(2), "B");

        t2.start();
        t1.start();
        t3.start();
    }

}