Java 循环屏障

Posted

技术标签:

【中文标题】Java 循环屏障【英文标题】:Java CyclicBarrier 【发布时间】:2016-06-10 12:59:03 【问题描述】:

我有多个线程发送同一个数据包,并希望所有线程都完成后再继续发送下一个数据包。

我使用以下代码测试了 CyclicBarrier:Test Code (was too long/messy to embed) 这可以按预期打印 0 - 4 的组合,然后在循环中完成

对于数据包发送方,代码是等价的,只是for循环是:

for(RSocket sendSocket : sendSocketList)
    new Thread(new Send(sendSocket , toServer)).start();

barrier.await();

发送是:

private class Send implements Runnable
    private RSocket sendSocket;
    private MPacket packet;
    public Send(RSocket sendSocket, MPacket packet)
        this.sendSocket = sendSocket;
        this.packet = packet;
    
    public void run()
        sendSocket.send(packet);
        try 
            barrier.await();
         catch (InterruptedException | BrokenBarrierException e) 
            // TODO Auto-generated catch block
            e.printStackTrace();
        
    

RSocket.send(数据包);功能与常规套接字的 writeObject() 函数相同,除了它会阻塞直到完成(当它接收到 ACK 时)。假设网络方面是正确的,我是否正确使用了 CyclicBarrier?

附:我应该指出,如果我使用 for 循环而不启动新线程,它会按预期工作,即:

for(RSocket sendSocket : sendSocketList)
    sendSocket.send(toServer);

【问题讨论】:

如果代码太长/太乱而无法发布,则将其缩减为一个完整的可编译、可运行的示例来演示问题。 @JimGarrison 对不起,我不能发布完整的代码,因为它涉及许多其他类并且也是一个项目。我链接的示例本质上是该特定类试图做的并且是可编译的。 您实际上并未提出问题或陈述问题。您看到的问题是什么? 有问题吗?如果不是,那么这是题外话,属于Code Review。 【参考方案1】:

是的,CyclicBarrier 在本例中的用法是正确的。

注意一点:

    根据代码,屏障必须初始化为sendSocketList.size()+1,因为还有主线程调用await()barrier = new CyclicBarrier(sendSocketList.size()+1);

【讨论】:

以上是关于Java 循环屏障的主要内容,如果未能解决你的问题,请参考以下文章

Java多线程-两种常用的线程计数器CountDownLatch和循环屏障CyclicBarrier

CyclicBarrier循环屏障相关

忙等待循环中是不是需要内存屏障或原子操作?

AQS同步组件-CyclicBarrier(循环屏障)解析和用例

我在哪里设置内存屏障以便条件循环观察多线程值的变化?

java并发编程之三--CyclicBarrier的使用