1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
| <span>import</span><span> org.slf4j.Logger; </span><span>import</span><span> org.slf4j.LoggerFactory; </span><span>import</span><span> org.springframework.stereotype.Component; </span> <span>public</span> <span>class</span><span> IdWorker {
</span><span>protected</span> <span>static</span> <span>final</span> Logger LOG = LoggerFactory.getLogger(IdWorker.<span>class</span><span>);
</span><span>private</span> <span>long</span><span> workerId; </span><span>private</span> <span>long</span><span> datacenterId; </span><span>private</span> <span>long</span> sequence = 0L<span>;
</span><span>private</span> <span>long</span> twepoch = 1288834974657L<span>;
</span><span>private</span> <span>long</span> workerIdBits = 5L<span>; </span><span>private</span> <span>long</span> datacenterIdBits = 5L<span>; </span><span>private</span> <span>long</span> maxWorkerId = -1L ^ (-1L <<<span> workerIdBits); </span><span>private</span> <span>long</span> maxDatacenterId = -1L ^ (-1L <<<span> datacenterIdBits); </span><span>private</span> <span>long</span> sequenceBits = 12L<span>;
</span><span>private</span> <span>long</span> workerIdShift =<span> sequenceBits; </span><span>private</span> <span>long</span> datacenterIdShift = sequenceBits +<span> workerIdBits; </span><span>private</span> <span>long</span> timestampLeftShift = sequenceBits + workerIdBits +<span> datacenterIdBits; </span><span>private</span> <span>long</span> sequenceMask = -1L ^ (-1L <<<span> sequenceBits);
</span><span>private</span> <span>long</span> lastTimestamp = -1L<span>;
</span><span>public</span> IdWorker(<span>long</span> workerId, <span>long</span><span> datacenterId) { </span><span>//</span><span> sanity check for workerId</span> <span>if</span> (workerId > maxWorkerId || workerId < 0<span>) { </span><span>throw</span> <span>new</span> IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0"<span>, maxWorkerId)); } </span><span>if</span> (datacenterId > maxDatacenterId || datacenterId < 0<span>) { </span><span>throw</span> <span>new</span> IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0"<span>, maxDatacenterId)); } </span><span>this</span>.workerId =<span> workerId; </span><span>this</span>.datacenterId =<span> datacenterId; LOG.info(String.format(</span>"worker starting. timestamp left shift %d, datacenter id bits %d, worker id bits %d, sequence bits %d, workerid %d"<span>, timestampLeftShift, datacenterIdBits, workerIdBits, sequenceBits, workerId)); }
</span><span>public</span> <span>synchronized</span> <span>long</span><span> nextId() { </span><span>long</span> timestamp =<span> timeGen();
</span><span>if</span> (timestamp <<span> lastTimestamp) { LOG.error(String.format(</span>"clock is moving backwards. Rejecting requests until %d."<span>, lastTimestamp)); </span><span>throw</span> <span>new</span> RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp -<span> timestamp)); }
</span><span>if</span> (lastTimestamp ==<span> timestamp) { sequence </span>= (sequence + 1) &<span> sequenceMask; </span><span>if</span> (sequence == 0<span>) { timestamp </span>=<span> tilNextMillis(lastTimestamp); } } </span><span>else</span><span> { sequence </span>= 0L<span>; }
lastTimestamp </span>=<span> timestamp;
</span><span>return</span> ((timestamp - twepoch) << timestampLeftShift) | (datacenterId << datacenterIdShift) | (workerId << workerIdShift) |<span> sequence; }
</span><span>protected</span> <span>long</span> tilNextMillis(<span>long</span><span> lastTimestamp) { </span><span>long</span> timestamp =<span> timeGen(); </span><span>while</span> (timestamp <=<span> lastTimestamp) { timestamp </span>=<span> timeGen(); } </span><span>return</span><span> timestamp; }
</span><span>protected</span> <span>long</span><span> timeGen() { </span><span>return</span><span> System.currentTimeMillis(); }
}</span>
|