线程交叉打印12A34B56C等
题目
线程交叉打印 123A34B56C ..., 一个线程打印数字, 一个线程打印字母;
解法一
基本思路
- 根据题目, 令线程
t1
打印数字, 线程t2
打印字母; - 使用
flag
来标记, 若为 false, 说明当前线程打印数字, 若为 true, 说明当前线程打印字母 - 使用
synchronized
来进行同步,wait()
方法让线程等待,notifyAll()
方法唤醒线程; - 需要注意字母最多打印到字符
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();
}
}
解法二
基本思路
- 使用
Semaphore
来控制两个线程的交换执行; - 同理, 打印字母最多打印到字符
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();
}
}