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

shz.core.id.SFIdProducer Maven / Gradle / Ivy

There is a newer version: 2024.0.2
Show newest version
package shz.core.id;

import shz.core.ToString;

public class SFIdProducer implements IdProducer {
    public static final SFIdProducer DEFAULT = new SFIdProducer(new IdInfo());

    private final long totalBits;
    protected final IdInfo idInfo;
    private final long datacenterIdResult, workerIdResult;

    /**
     * 起始时间戳,id中有效值 ,这个值的设置直接影响到id的使用年限
     */
    protected long startTimestamp = 1604764800000L;
    /**
     * 最后时间戳,防止时钟回拨
     */
    private long lastTimestamp;

    public SFIdProducer(IdInfo idInfo) {
        totalBits = idInfo.datacenterIdBits + idInfo.workerIdBits + idInfo.timestampBits + idInfo.sequenceBits;
        if (totalBits > 63L || totalBits < 52L) throw new IllegalArgumentException("id位数取值范围:52-63");
        if (idInfo.datacenterId > (~(-1L << idInfo.datacenterIdBits)) || idInfo.datacenterId < 0L)
            throw new IllegalArgumentException(ToString.format("中心节点取值范围:0-%d", ~(-1L << idInfo.datacenterIdBits)));
        if (idInfo.workerId > (~(-1L << idInfo.workerIdBits)) || idInfo.workerId < 0L)
            throw new IllegalArgumentException(ToString.format("工作节点取值范围:0-%d", ~(-1L << idInfo.workerIdBits)));
        this.idInfo = idInfo;

        datacenterIdResult = this.idInfo.datacenterId << (this.idInfo.sequenceBits + this.idInfo.workerIdBits);
        workerIdResult = this.idInfo.workerId << this.idInfo.sequenceBits;
    }

    public final void setStartTimestamp(long startTimestamp) {
        this.startTimestamp = startTimestamp;
    }

    public final void setLastTimestamp(long lastTimestamp) {
        this.lastTimestamp = lastTimestamp;
    }

    /**
     * 保存最后时间戳
     */
    protected void saveLastTimestamp(long lastTimestamp) {
    }

    /**
     * 同一毫秒内的自增序列
     */
    private long sequence;

    @Override
    public final synchronized Long next() {
        long timestamp = System.currentTimeMillis();
        if (timestamp < lastTimestamp)
            throw new RuntimeException(ToString.format("时钟回拨:%d毫秒", lastTimestamp - timestamp));
        if (timestamp == lastTimestamp) {
            sequence = (sequence + 1) & (~(-1L << idInfo.sequenceBits));
            if (sequence == 0L) {
                do {
                    timestamp = System.currentTimeMillis();
                } while (timestamp <= lastTimestamp);
                saveLastTimestamp(timestamp);
            }
        } else {
            sequence = 0L;
            saveLastTimestamp(timestamp);
        }
        lastTimestamp = timestamp;

        long timestampVal = (timestamp - startTimestamp) << (idInfo.sequenceBits + idInfo.workerIdBits + idInfo.datacenterIdBits);
        return (timestampVal & (~(-1L << totalBits)))
                | datacenterIdResult
                | workerIdResult
                | sequence;
    }

    @Override
    public final IdInfo analyze(Long id) {
        if (id == null) return null;
        IdInfo idInfo = new IdInfo();
        //可能是被截取的时间戳
        idInfo.timestamp = (id >>> (this.idInfo.sequenceBits + this.idInfo.workerIdBits + this.idInfo.datacenterIdBits)) + startTimestamp;
        idInfo.datacenterId = id >>> (this.idInfo.sequenceBits + this.idInfo.workerIdBits) & (~(-1L << this.idInfo.datacenterIdBits));
        idInfo.workerId = id >>> this.idInfo.sequenceBits & (~(-1L << this.idInfo.workerIdBits));
        idInfo.sequence = id & (~(-1L << this.idInfo.sequenceBits));

        idInfo.datacenterIdBits = this.idInfo.datacenterIdBits;
        idInfo.workerIdBits = this.idInfo.workerIdBits;
        idInfo.timestampBits = this.idInfo.timestampBits;
        idInfo.sequenceBits = this.idInfo.sequenceBits;
        return idInfo;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy