IdWorker.java 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. package com.jd.platform.jlog.common.utils;
  2. import java.net.InetAddress;
  3. import java.net.NetworkInterface;
  4. import java.text.SimpleDateFormat;
  5. import java.util.Calendar;
  6. import java.util.Date;
  7. import java.util.Enumeration;
  8. /**
  9. * 雪花算法(SnowFlake)
  10. *
  11. * @author wuweifeng
  12. * @version 1.0
  13. * @date 2021-08-23
  14. */
  15. public class IdWorker {
  16. private static final long EPOCH;
  17. private static final long SEQUENCE_BITS = 6L;
  18. private static final long WORKER_ID_BITS = 10L;
  19. private static final long SEQUENCE_MASK = (1 << SEQUENCE_BITS) - 1;
  20. private static final long WORKER_ID_LEFT_SHIFT_BITS = SEQUENCE_BITS;
  21. private static final long TIMESTAMP_LEFT_SHIFT_BITS = WORKER_ID_LEFT_SHIFT_BITS + WORKER_ID_BITS;
  22. private static final long WORKER_ID_MAX_VALUE = 1L << WORKER_ID_BITS;
  23. private static long workerId;
  24. static {
  25. Calendar calendar = Calendar.getInstance();
  26. calendar.set(2017, Calendar.APRIL, 1);
  27. calendar.set(Calendar.HOUR_OF_DAY, 0);
  28. calendar.set(Calendar.MINUTE, 0);
  29. calendar.set(Calendar.SECOND, 0);
  30. calendar.set(Calendar.MILLISECOND, 0);
  31. EPOCH = calendar.getTimeInMillis();
  32. initWorkerId();
  33. }
  34. private static long sequence;
  35. private static long lastTime;
  36. /**
  37. * 初始化workerId
  38. */
  39. private static void initWorkerId() {
  40. InetAddress address = getLocalAddress();
  41. byte[] ipAddressByteArray = address.getAddress();
  42. setWorkerId((long) (((ipAddressByteArray[ipAddressByteArray.length - 2] & 0B11) << Byte.SIZE) + (ipAddressByteArray[ipAddressByteArray.length - 1] & 0xFF)));
  43. }
  44. private static InetAddress getLocalAddress() {
  45. try {
  46. for (Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces(); interfaces.hasMoreElements(); ) {
  47. NetworkInterface networkInterface = interfaces.nextElement();
  48. if (networkInterface.isLoopback() || networkInterface.isVirtual() || !networkInterface.isUp()) {
  49. continue;
  50. }
  51. Enumeration<InetAddress> addresses = networkInterface.getInetAddresses();
  52. if (addresses.hasMoreElements()) {
  53. return addresses.nextElement();
  54. }
  55. }
  56. } catch (Exception e) {
  57. throw new IllegalStateException("Cannot get LocalHost InetAddress, please check your network!");
  58. }
  59. return null;
  60. }
  61. /**
  62. * 设置工作进程Id.
  63. *
  64. * @param workerId 工作进程Id
  65. */
  66. private static void setWorkerId(final Long workerId) {
  67. if (workerId >= 0L && workerId < WORKER_ID_MAX_VALUE) {
  68. IdWorker.workerId = workerId;
  69. } else {
  70. throw new RuntimeException("workerId is illegal");
  71. }
  72. }
  73. //下一个ID生成算法
  74. public static long nextId() {
  75. long time = System.currentTimeMillis();
  76. if (lastTime > time) {
  77. throw new RuntimeException("Clock is moving backwards, last time is %d milliseconds, current time is %d milliseconds" + lastTime);
  78. }
  79. if (lastTime == time) {
  80. if (0L == (sequence = ++sequence & SEQUENCE_MASK)) {
  81. time = waitUntilNextTime(time);
  82. }
  83. } else {
  84. sequence = 0;
  85. }
  86. lastTime = time;
  87. return ((time - EPOCH) << TIMESTAMP_LEFT_SHIFT_BITS) | (workerId << WORKER_ID_LEFT_SHIFT_BITS) | sequence;
  88. }
  89. private static long waitUntilNextTime(final long lastTime) {
  90. long time = System.currentTimeMillis();
  91. while (time <= lastTime) {
  92. time = System.currentTimeMillis();
  93. }
  94. return time;
  95. }
  96. }