All Downloads are FREE. Search and download functionalities are using the official Maven repository.

rpc.turbo.util.uuid.LongId Maven / Gradle / Ivy

package rpc.turbo.util.uuid;

import static java.time.ZoneOffset.UTC;

import java.time.LocalDateTime;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 每个jvm实例一个不重复的machineId,分配起来有点费劲
 * 
 * @author Hank
 *
 */
public final class LongId {

	private final static long NEW_EPOCH_MILLIS = LocalDateTime.parse("2017-01-01T00:00:00").toEpochSecond(UTC) * 1000L;

	private final int machineId;
	private final AtomicInteger counter = new AtomicInteger(0);
	private volatile int lastMinutes = 0;

	public LongId(int machineId) {
		if (machineId < 0 || machineId > 1 << 15) {
			throw new IllegalArgumentException("machineId must between 0, " + (1 << 15));
		}

		this.machineId = machineId;
	}

	private int getEpochMinutes() {
		long millis = System.currentTimeMillis() - NEW_EPOCH_MILLIS;
		int minutes = (int) (millis / 1000 / 60);
		return minutes;
	}

	/**
	 * 63年内有效
	 * 
	 * @return
	 */
	public long nextId() {
		int minutes = getEpochMinutes();

		if (lastMinutes != minutes) {
			synchronized (this) {
				minutes = getEpochMinutes();

				if (lastMinutes != minutes) {
					lastMinutes = minutes;
					counter.set(0);
				}
			}
		}

		int count = counter.getAndIncrement();
		if (count > (1 << 24)) {
			long millis = System.currentTimeMillis();

			try {
				long minuteMillis = TimeUnit.MINUTES.toMillis(1);

				Thread.sleep(millis / minuteMillis * minuteMillis - millis + minuteMillis);
			} catch (InterruptedException e) {
				throw new RuntimeException(e);
			}

			return nextId();
		}

		long id = (((long) minutes) << (64 - 25)) | (((long) machineId) << (64 - 25 - 15)) | count;

		return id;
	}

	public static void main(String[] args) {
		LongId idGenerator = new LongId(123);

		while (true) {
			long id = idGenerator.nextId();

			System.out.println(id);
		}
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy