Skip to content

线程交叉打印12A34B56C等

题目

线程交叉打印 123A34B56C ..., 一个线程打印数字, 一个线程打印字母;

解法一

基本思路

  1. 根据题目, 令线程 t1 打印数字, 线程 t2 打印字母;
  2. 使用 flag 来标记, 若为 false, 说明当前线程打印数字, 若为 true, 说明当前线程打印字母
  3. 使用 synchronized 来进行同步, wait() 方法让线程等待, notifyAll() 方法唤醒线程;
  4. 需要注意字母最多打印到字符C, 并非无限打印;

实现代码

java
public class ThreadsCrossPrint12A {

    // 打印标记 true打印数字 false打印字母
    private static boolean flag = true;

    // 锁
    private static final Object LOCK = new Object();

    public static void main(String[] args) throws InterruptedException {

        Thread t1 = new Thread(() -> {
            for (int i = 1; i <= 52; i += 2) {
                synchronized (LOCK) {
                    while (!flag) {
                        // 当前轮到打印字母时 让打印数字的线程等待
                        try {
                            LOCK.wait();
                        } catch (InterruptedException e) {
                            throw new RuntimeException(e);
                        }
                    }
                    // 执行打印
                    System.out.print(i);
                    System.out.print(i+1);
                    // 休眠1秒 效果更明显
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                    // 打印数字结束后 轮到打印字母
                    flag = false;
                    LOCK.notifyAll();
                }
            }
        }, "t1");
        Thread t2 = new Thread(() -> {
            for (int c = 0; c < 26; ++ c) {
                synchronized (LOCK) {
                    while (flag) {
                        // 当前轮到打印数字时 让打印字母的线程等待
                        try {
                            LOCK.wait();
                        } catch (InterruptedException e) {
                            throw new RuntimeException(e);
                        }
                    }
                    // 执行打印
                    System.out.print((char)  (c + 'A'));
                    // 休眠1秒 效果更明显
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                    // 打印字母结束后 轮到打印数字
                    flag = true;
                    LOCK.notifyAll();
                }
            }
        }, "t2");
        t2.start();
        t1.start();
    }

}

解法二

基本思路

  1. 使用 Semaphore 来控制两个线程的交换执行;
  2. 同理, 打印字母最多打印到字符 C;

实现代码

java
public class ThreadsCrossPrint12A_2 {

    public static void main(String[] args) {
        Semaphore first = new Semaphore(0);
        Semaphore second = new Semaphore(0);
        Thread t1 = new Thread(() -> {
            for (int i = 1; i <= 52; i += 2) {
                try {
                    // 先打印数字
                    System.out.print(i);
                    System.out.print(i+1);
                    // 打印后休眠一秒 突出效果
                    Thread.sleep(1000);
                    // 唤醒 second 附近线程
                    second.release();
                    // 再阻塞当前打印数字线程
                    first.acquire();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        }, "t1");
        Thread t2 = new Thread(() -> {
            for (int i = 0; i < 26; ++ i) {
                try {
                    // 先阻塞当前线程 保证打印数字的线程先打印
                    second.acquire();
                    // 打印字母
                    System.out.print((char)(i + 'A'));
                    // 打印后休眠一秒 突出效果
                    Thread.sleep(1000);
                    // 唤醒打印数字的线程
                    first.release();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        }, "t2");
        t2.start();
        t1.start();
    }
}