接口 ProducerBarrier

所有超级接口:
SequenceBarrier
所有已知实现类:
MpUnboundedBufferSequencer, MultiProducerSequencer, RingBufferSequencer, SingleProducerSequencer

public interface ProducerBarrier extends SequenceBarrier
生产者序号屏障 1. 生产者屏障负责的是生产者与生产者之间,生产者和消费者之间的协调。
2. 生产者与消费最慢的消费者之间进行协调 -- SequenceBarrier.dependentSequence()即为最慢的消费者进度,如果有消费者的话。
3. 生产者之间可能毫无关系,因此生产者之间的协调需要由屏障实现。
4. 生产者由于明确知道自己要生产的数据数量,因此tryNext(n)的接口更易于使用。

Q: 生产者为什么没有等待策略?
A:一开始我确实尝试添加等待策略,后来发现没有意义。我在SequenceBlocker中提到,生产者不能使用Condition等待消费者, 因此等待策略的扩展性很有限,除了短暂的挂起线程外,没有好的替代方法。

Q: 生产者为什么没有ConsumerBarrier.alert()信号? A:我们将生产者归属于外部系统,而将消费者归属于内部系统。生产者可能仅有部分逻辑与Sequencer相关,我们不能使用alert信号来中断或终止生产者。

作者:
wjybxx date - 2024/1/16
  • 方法详细资料

    • hasAvailableCapacity

      boolean hasAvailableCapacity(int requiredCapacity)
      是否有足够的空间 Has the buffer got capacity to allocate another sequence. This is a concurrent method so the response should only be taken as an indication of available capacity.
      参数:
      requiredCapacity - in the buffer
      返回:
      true if the buffer has the capacity to allocate the next sequence otherwise false.
    • next

      long next()
      获取下一个事件的序号,空间不足时会阻塞(等待)。 申请完空间之后,必须使用 publish(long) 发布,否则会导致整个数据结构不可用。

      Claim the next event in sequence for publishing.

      返回:
      the claimed sequence value
    • next

      long next(int n)
      获取接下来的n个事件的序号,空间不足时会阻塞(等待)。 申请完空间之后,必须使用 publish(long, long) 发布,否则会导致整个数据结构不可用

      Claim the next n events in sequence for publishing. This is for batch event producing. Using batch producing requires a little care and some math.

       int n = 10;
       long hi = sequencer.next(n);
       long lo = hi - (n - 1);
       for (long sequence = lo; sequence <= hi; sequence++) {
           // Do work.
       }
       sequencer.publish(lo, hi);
       
      参数:
      n - the number of sequences to claim
      返回:
      the highest claimed sequence value
    • tryNext

      long tryNext()
      尝试获取下一个事件的序列,空间不足时抛出异常。 申请完空间之后,必须使用 publish(long) 发布,否则会导致整个数据结构不可用。

      Attempt to claim the next event in sequence for publishing. Will return the number of the slot if there is at least requiredCapacity slots available.

      返回:
      申请成功则返回对应的序号,否则返回 -1
    • tryNext

      long tryNext(int n)
      尝试获取接下来n个数据的最后一个数据索引位置。不会阻塞,空间不足时抛出异常。 申请完空间之后,必须使用 publish(long, long) 发布,否则会导致整个数据结构不可用 使用该方法可以避免死锁

      Attempt to claim the next n events in sequence for publishing. Will return the highest numbered slot if there is at least requiredCapacity slots available. Have a look at next() for a description on how to use this method.

      参数:
      n - 需要申请的序号数量
      返回:
      申请成功则返回对应的序号,否则返回 -1
    • publish

      void publish(long sequence)
      发布指定序号的数据,表示sequence对应的数据可用 Publishes a sequence. Call when the event has been filled.
      参数:
      sequence - the sequence to be published.
    • publish

      void publish(long lo, long hi)
      批量发布数据,表示 [lowest,highest]区间段整段数据可用。 一般情况下,hinext()等方法申请到的最大序号,但也可能不是,生产者可能分段发布数据,以避免阻塞消费者。

      Batch publish sequences. Called when all of the events have been filled.

      参数:
      lo - first sequence number to publish
      hi - last sequence number to publish
    • isPublished

      boolean isPublished(long sequence)
      指定序号的数据是否已发布。 注意: 1. 该测试只测试序号自身,不测试其前置序号。 2. 通常情况下你不应该使用它,唯一合理的情况是:清理RingBuffer的时候。

      Confirms if a sequence is published and the event is available for use; non-blocking.

      参数:
      sequence - of the buffer to check
      返回:
      true if the sequence is available for use, false if not
    • getHighestPublishedSequence

      long getHighestPublishedSequence(long nextSequence, long availableSequence)
      查询 [nextSequence , availableSequence] 区间段之间连续发布的最大序号。 该接口用于消费者屏障查询真实可用的序号。

      由于多线程的生产者是先申请序号,再发布数据;因此SequenceBarrier.sequence()指向的是即将发布数据的槽,而不一定已经具备数据。 而消费者只能顺序消费,因此【只要消费者的依赖可能包含生产者】,在观察到依赖的最大可用序号后,都应该查询真实可用的序号。

      Get the highest sequence number that can be safely read from the ring buffer. Depending on the implementation of the Sequencer this call may need to scan a number of values in the Sequencer. The scan will range from nextSequence to availableSequence. If there are no available values >= nextSequence the return value will be nextSequence - 1. To work correctly a consumer should pass a value that is 1 higher than the last sequence that was successfully processed.

      参数:
      nextSequence - The sequence to start scanning from.
      availableSequence - The sequence to scan to.
      返回:
      The highest value that can be safely read, will be at least nextSequence - 1.
    • nextInterruptibly

      long nextInterruptibly() throws InterruptedException
      next()基础上会响应中断请求
      抛出:
      InterruptedException - 如果申请期间线程被中断
    • nextInterruptibly

      long nextInterruptibly(int n) throws InterruptedException
      next(int)基础上会响应中断请求
      抛出:
      InterruptedException - 如果申请期间线程被中断
    • tryNext

      long tryNext(int n, long timeout, TimeUnit unit)
      在给定时间内尝试申请序号 注意:受限于等待策略的扩展限制,该接口本质是tryNext(int)的循环快捷方法。
      参数:
      n - 需要申请的序号数量
      返回:
      申请成功则返回对应的序号,否则返回 -1
    • getBlocker

      @Nullable SequenceBlocker getBlocker()
      获取用于阻塞等待序号的阻塞器。 注意:可能为null,如果整个系统禁用了基于锁的条件等待。
    • signalAllWhenBlocking

      void signalAllWhenBlocking()
      唤醒所有因条件等待阻塞的线程 getBlocker()的快捷方法