com.hazelcast.simulator.worker.metronome.SimpleMetronome.java Source code

Java tutorial

Introduction

Here is the source code for com.hazelcast.simulator.worker.metronome.SimpleMetronome.java

Source

/*
 * Copyright (c) 2008-2015, Hazelcast, Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.hazelcast.simulator.worker.metronome;

import java.util.concurrent.TimeUnit;

import static java.lang.Math.round;
import static org.apache.commons.lang3.RandomUtils.nextLong;

/**
 * Simple {@link Metronome} implementation which busy loops on a fixed interval.
 *
 * The wait interval on the first {@link #waitForNext()} call is randomized.
 *
 * It is recommended to create a new instance for each worker thread, so they are clocked interleaved.
 */
public final class SimpleMetronome implements Metronome {

    private static final Metronome EMPTY_METRONOME = new EmptyMetronome();

    private final long intervalNanos;

    private long waitUntil;

    private SimpleMetronome(long intervalNanos) {
        this.intervalNanos = intervalNanos;
    }

    /**
     * Creates a {@link Metronome} instance with a fixed millisecond interval.
     *
     * @param intervalMs wait interval in milliseconds
     * @return a {@link Metronome} instance
     */
    public static Metronome withFixedIntervalMs(int intervalMs) {
        if (intervalMs == 0) {
            return EMPTY_METRONOME;
        }
        return new SimpleMetronome(TimeUnit.MILLISECONDS.toNanos(intervalMs));
    }

    /**
     * Creates a {@link Metronome} instance with a fixed frequency in Hz.
     *
     * If the frequency is 0 Hz the method {@link #waitForNext()} will have no delay.
     *
     * @param frequency frequency
     * @return a {@link Metronome} instance
     */
    public static Metronome withFixedFrequency(float frequency) {
        if (frequency == 0) {
            return EMPTY_METRONOME;
        }

        long intervalNanos = round((double) TimeUnit.SECONDS.toNanos(1) / frequency);
        return new SimpleMetronome(intervalNanos);
    }

    @Override
    public void waitForNext() {
        // set random interval on the first run
        if (waitUntil == 0) {
            waitUntil = System.nanoTime() + nextLong(0, intervalNanos);
        }

        // busy loop
        long now;
        do {
            now = System.nanoTime();
        } while (now < waitUntil);

        // set regular interval for next call
        waitUntil = now + intervalNanos;
    }

    private static class EmptyMetronome implements Metronome {

        @Override
        public void waitForNext() {
        }
    }
}