# 1、使用三个线程按顺序打印ABC,循环打印10次

# 基础实现

使用三个线程按顺序打印ABC,并循环打印10次,可以通过以下方法实现:

# 实现逻辑

利用线程间通信机制,例如 synchronizedwait/notify,确保三个线程按照固定顺序执行。每个线程打印一个特定的字符后,通知下一个线程继续,形成循环。

# 完整代码

public class PrintABC {
    private static final int MAX_PRINT_COUNT = 10; // 循环打印次数
    private static int state = 0; // 线程状态,0表示打印A,1表示打印B,2表示打印C

    public static void main(String[] args) {
        Object lock = new Object();

        Thread threadA = new Thread(() -> {
            for (int i = 0; i < MAX_PRINT_COUNT; i++) {
                synchronized (lock) {
                    while (state % 3 != 0) { // 轮到A打印
                        try {
                            lock.wait();
                        } catch (InterruptedException e) {
                            Thread.currentThread().interrupt();
                        }
                    }
                    System.out.print("A");
                    state++;
                    lock.notifyAll();
                }
            }
        });

        Thread threadB = new Thread(() -> {
            for (int i = 0; i < MAX_PRINT_COUNT; i++) {
                synchronized (lock) {
                    while (state % 3 != 1) { // 轮到B打印
                        try {
                            lock.wait();
                        } catch (InterruptedException e) {
                            Thread.currentThread().interrupt();
                        }
                    }
                    System.out.print("B");
                    state++;
                    lock.notifyAll();
                }
            }
        });

        Thread threadC = new Thread(() -> {
            for (int i = 0; i < MAX_PRINT_COUNT; i++) {
                synchronized (lock) {
                    while (state % 3 != 2) { // 轮到C打印
                        try {
                            lock.wait();
                        } catch (InterruptedException e) {
                            Thread.currentThread().interrupt();
                        }
                    }
                    System.out.print("C");
                    state++;
                    lock.notifyAll();
                }
            }
        });

        // 启动三个线程
        threadA.start();
        threadB.start();
        threadC.start();
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64

# 代码说明

  1. 状态控制
    • 使用 state 变量来控制打印的顺序:0 对应线程A打印,1 对应线程B打印,2 对应线程C打印。
    • 每次打印完成后,状态加1,确保轮流打印。
  2. 锁与线程通信
    • 使用 synchronized 关键字和 wait/notifyAll 方法实现线程通信。
    • 当前线程执行时,其他线程阻塞,直到调用 notifyAll 唤醒。
  3. 循环次数
    • 每个线程循环打印 MAX_PRINT_COUNT 次,保证打印完成10个“ABC”。

# 输出结果

ABCABCABCABCABCABCABCABCABCABC
1

# 高级扩展

如果需要更灵活的实现,可以使用 ReentrantLockCondition,或者基于更高级的工具类如 SemaphoreCyclicBarrier 来实现类似功能。

以下是使用 ReentrantLockCondition 实现的扩展版本,具有更高的灵活性和控制能力:

# 扩展-ReentrantLockCondition

# 代码实现

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

public class PrintABCWithLock {
    private static final int MAX_PRINT_COUNT = 10; // 循环打印次数
    private static int state = 0; // 线程状态,0表示打印A,1表示打印B,2表示打印C

    public static void main(String[] args) {
        Lock lock = new ReentrantLock();
        Condition conditionA = lock.newCondition();
        Condition conditionB = lock.newCondition();
        Condition conditionC = lock.newCondition();

        Thread threadA = new Thread(() -> {
            for (int i = 0; i < MAX_PRINT_COUNT; i++) {
                lock.lock();
                try {
                    while (state % 3 != 0) {
                        conditionA.await(); // 等待轮到A打印
                    }
                    System.out.print("A");
                    state++;
                    conditionB.signal(); // 通知线程B
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                } finally {
                    lock.unlock();
                }
            }
        });

        Thread threadB = new Thread(() -> {
            for (int i = 0; i < MAX_PRINT_COUNT; i++) {
                lock.lock();
                try {
                    while (state % 3 != 1) {
                        conditionB.await(); // 等待轮到B打印
                    }
                    System.out.print("B");
                    state++;
                    conditionC.signal(); // 通知线程C
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                } finally {
                    lock.unlock();
                }
            }
        });

        Thread threadC = new Thread(() -> {
            for (int i = 0; i < MAX_PRINT_COUNT; i++) {
                lock.lock();
                try {
                    while (state % 3 != 2) {
                        conditionC.await(); // 等待轮到C打印
                    }
                    System.out.print("C");
                    state++;
                    conditionA.signal(); // 通知线程A
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                } finally {
                    lock.unlock();
                }
            }
        });

        // 启动三个线程
        threadA.start();
        threadB.start();
        threadC.start();
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74

# 代码说明

  1. ReentrantLockCondition
    • 使用 ReentrantLock 来控制线程同步,避免竞争条件。
    • 每个线程有自己的 Condition(如 conditionAconditionBconditionC),用于线程间的精确通信。
  2. 状态控制
    • 通过 state % 3 判断当前轮到哪个线程执行,类似于之前的 synchronized 版本。
  3. 通知机制
    • await():当前线程进入等待状态,直到被其他线程通过 signal() 唤醒。
    • signal():唤醒下一个线程,确保按顺序执行。

# 输出结果

ABCABCABCABCABCABCABCABCABCABC
1

# 扩展实现:使用 Semaphore

Semaphore 是一种信号量机制,也可以用来控制线程的执行顺序:

# 代码实现

import java.util.concurrent.Semaphore;

public class PrintABCWithSemaphore {
    private static final int MAX_PRINT_COUNT = 10; // 循环打印次数

    public static void main(String[] args) {
        Semaphore semaphoreA = new Semaphore(1); // A线程初始可以运行
        Semaphore semaphoreB = new Semaphore(0); // B线程初始阻塞
        Semaphore semaphoreC = new Semaphore(0); // C线程初始阻塞

        Thread threadA = new Thread(() -> {
            for (int i = 0; i < MAX_PRINT_COUNT; i++) {
                try {
                    semaphoreA.acquire(); // 获取许可
                    System.out.print("A");
                    semaphoreB.release(); // 通知线程B
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        });

        Thread threadB = new Thread(() -> {
            for (int i = 0; i < MAX_PRINT_COUNT; i++) {
                try {
                    semaphoreB.acquire(); // 获取许可
                    System.out.print("B");
                    semaphoreC.release(); // 通知线程C
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        });

        Thread threadC = new Thread(() -> {
            for (int i = 0; i < MAX_PRINT_COUNT; i++) {
                try {
                    semaphoreC.acquire(); // 获取许可
                    System.out.print("C");
                    semaphoreA.release(); // 通知线程A
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        });

        // 启动三个线程
        threadA.start();
        threadB.start();
        threadC.start();
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

# 扩展分析

  1. ReentrantLock vs Semaphore
    • ReentrantLock 更灵活,可管理多个条件变量,适用于复杂线程间的精准通信。
    • Semaphore 更简单,适合用于控制有限资源的访问和固定顺序的线程调度。
  2. 选择建议
    • 如果场景较复杂,推荐使用 ReentrantLockCondition
    • 如果只需要简单的线程顺序控制,可以用 Semaphore 提高代码可读性。