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
:等待字母线程。- 循环执行上述步骤。
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。