Java CyclicBarrier错误使用的实例
作者:学亮编程手记
文章描述了一个Java程序使用CyclicBarrier实现两个线程交替打印字母和数字时遇到的问题,由于线程执行顺序不当,导致输出结果与预期不符,通过调整线程的等待和打印顺序,解决了问题,文章还提供了一个控制流图来详细解释修改前后的程序逻辑
Java CyclicBarrier错误使用
错误代码示例
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
public class AlternatePrintCyclicBarrier {
private static final CyclicBarrier barrier = new CyclicBarrier(2);
public static void main(String[] args) {
String letters = "abcd";
String numbers = "1234";
Thread letterThread = new Thread(() -> {
for (char letter : letters.toCharArray()) {
try {
System.out.print(letter);
barrier.await(); // 等待另一个线程
} catch (InterruptedException | BrokenBarrierException e) {
Thread.currentThread().interrupt();
}
}
});
Thread numberThread = new Thread(() -> {
for (char number : numbers.toCharArray()) {
try {
barrier.await(); // 等待字母线程
System.out.print(number);
} catch (InterruptedException | BrokenBarrierException e) {
Thread.currentThread().interrupt();
}
}
});
letterThread.start();
numberThread.start();
try {
letterThread.join();
numberThread.join();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
代码错误分析
当前代码的逻辑是两个线程交替打印字母和数字,但是由于CyclicBarrier的使用不当,导致输出结果为ab12cd34。
具体原因是在字母线程中先打印字母再等待,而在数字线程中先等待再打印数字,这会导致字母线程先打印两个字母后,数字线程才开始打印。
修改方案
为了实现交替打印的效果,可以调整线程的执行顺序。
具体来说,可以让字母线程先等待,然后打印字母;而数字线程先等待,然后打印数字。这样可以确保两个线程交替执行。
修改后的代码
package com.zxl.a1b2c3d4;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
public class AlternatePrintCyclicBarrier {
private static final CyclicBarrier barrier = new CyclicBarrier(2);
public static void main(String[] args) {
String letters = "abcd";
String numbers = "1234";
Thread letterThread = new Thread(() -> {
for (char letter : letters.toCharArray()) {
try {
barrier.await(); // 等待数字线程
System.out.print(letter);
barrier.await(); // 等待数字线程
} catch (InterruptedException | BrokenBarrierException e) {
Thread.currentThread().interrupt();
}
}
});
Thread numberThread = new Thread(() -> {
for (char number : numbers.toCharArray()) {
try {
barrier.await(); // 等待字母线程
System.out.print(number);
barrier.await(); // 等待字母线程
} catch (InterruptedException | BrokenBarrierException e) {
Thread.currentThread().interrupt();
}
}
});
letterThread.start();
numberThread.start();
try {
letterThread.join();
numberThread.join();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
修改后的控制流图

详细解释
- Start:程序开始。
- CreateThreads:创建两个线程,一个用于打印字母,一个用于打印数字。
- StartThreads:启动这两个线程。
- WaitThreads:主线程调用
join方法等待两个子线程执行完毕。 - End:程序结束。
在子图中:
字母线程:
AwaitNumber1:等待数字线程。PrintLetter:打印字母。AwaitNumber2:等待数字线程。- 循环执行上述步骤。
数字线程:
AwaitLetter1:等待字母线程。PrintNumber:打印数字。AwaitLetter2:等待字母线程。- 循环执行上述步骤。
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。
