public boolean addConsumer( final C consumer,
                                final int timesToRetryUponTimeout ) {
        if (!addEntries.get()) {
            throw new IllegalStateException();
        }
        ConsumerRunner runner = new ConsumerRunner(consumer, timesToRetryUponTimeout);
        if (gcConsumer != null) gcConsumer.stayBehind(runner.getPointer());

        // Try to add the runner instance, with equality based upon consumer instance equality ...
        if (!consumers.add(runner)) return false;

        // It was added, so start it ...
        executor.execute(runner);
        return true;
    }
public boolean addConsumer ( final C consumer , final int timesToRetryUponTimeout ) { if ( ! addEntries . get ( ) ) { throw new IllegalStateException ( ) ; } ConsumerRunner runner = new ConsumerRunner ( consumer , timesToRetryUponTimeout ) ; if ( gcConsumer != null ) gcConsumer . stayBehind ( runner . getPointer ( ) ) ; if ( ! consumers . add ( runner ) ) return false ; executor . execute ( runner ) ; return true ; }
Add the supplied consumer, and have it start processing entries in a separate thread.
<p>
The consumer is automatically removed from the ring buffer when it returns {@code false} from its
{@link Consumer#consume(Object, long, long)} method.
</p>

@param consumer the component that will process the entries; may not be null
@param timesToRetryUponTimeout the number of times that the thread should retry after timing out while waiting for the next
entry; retries will not be attempted if the value is less than 1
@return true if the consumer was added, or false if the consumer was already registered with this buffer
@throws IllegalStateException if the ring buffer has already been {@link #shutdown()}