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

shz.id.SFIdProducer Maven / Gradle / Ivy

package shz.id;

import shz.Help;
import shz.msg.ServerFailureMsg;

public class SFIdProducer implements IdProducer {
    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;
        ServerFailureMsg.requireNon(
                totalBits > 63L || totalBits < 52L,
                "id位数取值范围:52-63"
        );
        ServerFailureMsg.requireNon(
                idInfo.datacenterId > (~(-1L << idInfo.datacenterIdBits)) || idInfo.datacenterId < 0L,
                "中心节点取值范围:0-%d",
                ~(-1L << idInfo.datacenterIdBits)
        );
        ServerFailureMsg.requireNon(
                idInfo.workerId > (~(-1L << idInfo.workerIdBits)) || idInfo.workerId < 0L,
                "工作节点取值范围: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(Help.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 - 2025 Weber Informatics LLC | Privacy Policy