Support for distributed id generators

import java.util.concurrent.atomic.AtomicInteger;

/**
* The bits here are from the high order, and the first bit is the sign bit.
* 1bit + 41bit + 17bit + 5bit
* The 1st bit is fixed at 0 and the sign bit does not change.
* The 2nd to 42th bits use the time delay, accurate to the millisecond 41bit. The service life is 69 years
* The 43rd to 59th bits use the self-incrementing serial number 17bit The maximum number of available serial numbers is 131071, which means that we can generate 131071 different serial numbers in one millisecond.
* The 60th to 64th bits use machine code 5bit to make the system distributed, and the maximum number of distributed machines is 32 machines.
* @author pdy
*/
public class IDGennerator {

//The maximum serial number of 17bit is 131071
private final static int max_orderNo = 131071;
//Used to generate the serial number
private AtomicInteger orderNo;
//Machine code (0-31)
private final static long machineCode = 31l;
//mask of timestamps
private final static long time_code = Long.MAX_VALUE >>> 22;



public IDGennerator() {
orderNo = new AtomicInteger(0);
}

public long genneratorId(){
/**
* Timestamp 
* 1. Remove the high 23bit first and keep the current The low 41bit of the time
* 2, move 0 to 41bit to the high position
*/
long currentTimeMillis = (System.currentTimeMillis() & time_code) << 22;

/**
* The serial number is incremented by 1 and obtained
*/
int orderNo = this .orderNo.incrementAndGet();
if(orderNo > max_orderNo){
//If the maximum sequence number is exceeded, reset to 0
if(!this.orderNo.compareAndSet(orderNo, 0)){
//The cas operation is used here, so No need to lock 1. If the operation fails, it means that other threads have changed the data, so you can directly increment and get it.
orderNo = this.orderNo.incrementAndGet();
} else {
//After the operation is successful, the serial number is 0
orderNo = 0;
}
}
//Sign bit (1) bit, timestamp (2~42) bit | serial number (43~59) bit | machine code (60~64) bit
currentTimeMillis = currentTimeMillis | (orderNo << 14 >>> 9) | machineCode;
return currentTimeMillis;
}





//Upgraded version

package com.hengyunsoft.util;

import java.text.SimpleDateFormat;
import java.util .Calendar;
import java.util.concurrent.atomic.AtomicInteger;

/** *
1bit + 41bit + 17bit + 5bit *
| | | |
* | | | | Fixed is 0 and the sign bit does not move. * The 2nd to 42th bits use the time delay, accurate to the millisecond 41bit. The service life is 69 years



* The 43rd to 59th bits use self-incrementing serial numbers. 17bit has a maximum of 131071 available serial numbers, which means that we can generate 131071 different serial numbers in one millisecond.
* The 60th to 64th bits use machine code 5bit to make the system distributed, and the maximum number of distributed machines is 32 machines.
* @author pdy
*/
public class SnowflakeIDGenerate implements IIDGenerate<Long>{

//The maximum serial number of 17bit is 131071
private final static int max_orderNo = 131071;
//Used to generate the serial number
private AtomicInteger orderNo;
//Machine code (0- 31)
private final long machineCode;
//mask for timestamp
private final static long time_code = Long.MAX_VALUE >>> 22;
/**
* 2015-01-01 00:00:00
* 1420041600210
* because our generator It can be used for 69 years, and we want the generated id to increase gradually during these times.
* So here I specify when to start using the id generator.
*/
private final long startTime = 1420041600210L;
public SnowflakeIDGenerate(final long machineCode) {
if( 0 > machineCode || machineCode > 31){
throw new IllegalArgumentException("Please note that 1. The machine code is not allowed to be repeated between multiple machines or applications Yes! 2. The machine code value is only between 0 and 31");
}
this.machineCode = machineCode;
orderNo = new AtomicInteger(0);
}

public Long generate(){
/**
* Timestamp 
* 1. First Remove the high 23 bits, keep the low 41 bits of the current time
* 2, move 0 to 41 bits to the high bits
*/
long currentTimeMillis = time_code & (System.currentTimeMillis() - startTime) << 22;

/**
* The serial number is incremented by 1 and get
*/
int orderNo = this.orderNo.incrementAndGet();
if(orderNo > max_orderNo){
//If the maximum serial number is exceeded, reset to 0
if(!this.orderNo.compareAndSet(orderNo, 0)){
//The cas operation is used here, so there is no need to lock 1. If the operation fails, it means other threads If the data has been changed, it is OK to directly increment and get it
orderNo = this.orderNo.incrementAndGet();
} else {
//After the operation is successful, the serial number is 0
orderNo = 0;
}
}
//Sign bit (1) bit, timestamp (2~42) bit | serial number (43~59) bit | machine code (60~64) bit
return currentTimeMillis | (orderNo << 14 >>> 9) | machineCode;
}
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326522160&siteId=291194637