如何解决synchronized块下ping/pong仅打印一次,实现5次交替输出?
解决Ping-Pong交替打印5次的问题
你的代码只执行一次就停滞,核心原因是缺少循环控制打印次数,以及没有状态标记来明确当前该哪个线程执行。以下是修改后的完整实现:
修改后的AA类代码
class AA { // 标记当前是否轮到打印ping private boolean isPingTurn = true; // 记录打印轮次,总共完成5轮即停止 private int roundCount = 0; public void ping() { synchronized (this) { // 循环等待:直到轮到ping且未完成5轮 while (!isPingTurn || roundCount >= 5) { try { wait(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); return; } } System.out.println("ping"); roundCount++; isPingTurn = false; // 切换为pong的回合 notifyAll(); // 唤醒等待的pong线程 } } public void pong() { synchronized (this) { // 循环等待:直到轮到pong且未完成5轮 while (isPingTurn || roundCount >= 5) { try { wait(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); return; } } System.out.println("pong"); isPingTurn = true; // 切换为ping的回合 notifyAll(); // 唤醒等待的ping线程 } } }
修改后的主类代码
public class Main { public static void main(String[] args) { AA aa = new AA(); // ping线程:循环调用ping方法5次 new Thread(() -> { for (int i = 0; i < 5; i++) { aa.ping(); } }).start(); // pong线程:循环调用pong方法5次 new Thread(() -> { for (int i = 0; i < 5; i++) { aa.pong(); } }).start(); } }
关键修改点说明
- 状态标记
isPingTurn:明确当前线程是否有执行权限,避免线程被无序唤醒后直接执行。 - 循环等待逻辑:用
while而非if判断状态,防止虚假唤醒(线程被唤醒后需再次确认是否满足执行条件)。 - 轮次控制:通过类内的
roundCount或线程内的循环,确保总共完成5轮交替打印。 - 中断处理:捕获
InterruptedException后恢复线程中断状态,保证线程能正确终止。
运行后会输出:
ping pong ping pong ping pong ping pong ping pong
内容的提问来源于stack exchange,提问作者Sungjoon Ha
相关产品推荐
相关产品推荐

