1. Overview

In this tutorial, we’ll learn how to implement a Ring Buffer in Java.

2. Ring Buffer

Ring Buffer (or Circular Buffer) is a bounded circular data structure that is used for buffering data between two or more threads. As we keep writing to a ring buffer, it wraps around as it reaches the end.

2.1. How it Works

A Ring Buffer is implemented using a fixed-size array that wraps around at the boundaries.

Apart from the array, it keeps track of three things:

  • the next available slot in the buffer to insert an element,
  • the next unread element in the buffer,
  • and the end of the array – the point at which the buffer wraps around to the start of the array

The mechanics of how a ring buffer handles these requirements vary with the implementation. For instance, the Wikipedia entry on the subject shows a method using four-pointers.

We’ll borrow the approach from Disruptor‘s implementation of the ring buffer using sequences.

The first thing we need to know is the capacity – the fixed maximum size of the buffer. Next, we’ll use two monotonically increasing sequences:

  • Write Sequence: starting at -1, increments by 1 as we insert an element
  • Read Sequence: starting at 0, increments by 1 as we consume an element

We can map a sequence to an index in the array by using a mod operation:

1

arrayIndex = sequence % capacity

The mod operation wraps the sequence around the boundaries to derive a slot in the buffer:

Let’s see how we’d insert an element:

1

buffer[++writeSequence % capacity] = element

We are pre-incrementing the sequence before inserting an element.

To consume an element we do a post-increment:

1

element = buffer[readSequence++ % capacity]

In this case, we perform a post-increment on the sequence. Consuming an element doesn’t remove it from the buffer – it just stays in the array until it’s overwritten.

2.2. Empty and Full Buffers

#algorithms #java

Implementing a Ring Buffer in Java
10.90 GEEK