java 生成 序列号_Java并发编程-生成唯一序列号
所用到的并發編程庫
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantReadWriteLock;
package com.league.idgenerate;
/**
*
* ID生成器接口, 用于生成全局唯一的ID流水號
*
* @author Ivan.Ma
*/
public interface IdGenerator {
/**
* 生成下一個不重復的流水號
* @return
*/
String next();
}
package com.league.idgenerate;
/**
* ID生成器的配置接口
* @author Ivan.Ma
*/
public interface IdGeneratorConfig {
/**
* 獲取分隔符
* @return
*/
String getSplitString();
/**
* 獲取初始值
* @return
*/
int getInitial();
/**
* 獲取ID前綴
* @return
*/
String getPrefix();
/**
* 獲取滾動間隔, 單位: 秒
* @return
*/
int getRollingInterval();
}
package com.league.idgenerate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* 默認的ID生成器, 采用前綴+時間+原子數的形式實現
* 建議相同的配置采用同一個實例
* @see IdGeneratorConfig
* @author Ivan.Ma
*/
public class DefaultIdGenerator implements IdGenerator, Runnable{
private String time;
private AtomicInteger value;
private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
private IdGeneratorConfig config;
private Thread thread;
private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
public DefaultIdGenerator(){
config = new DefaultIdGeneratorConfig();
time = LocalDateTime.now().format(FORMATTER);
value = new AtomicInteger(config.getInitial());
thread = new Thread(this);
thread.setDaemon(true);
thread.start();
}
public DefaultIdGenerator(IdGeneratorConfig config){
this.config = config;
time = LocalDateTime.now().format(FORMATTER);
value = new AtomicInteger(config.getInitial());
thread = new Thread(this);
thread.setDaemon(true);
thread.start();
}
@Override
public String next() {
lock.readLock().lock();
StringBuffer sb = new StringBuffer(config.getPrefix()).append(config.getSplitString()).append(time).append(config.getSplitString()).append(value.getAndIncrement());
lock.readLock().unlock();
return sb.toString();
}
@Override
public void run() {
while (true){
try {
Thread.sleep(1000 * config.getRollingInterval());
} catch (InterruptedException e) {
e.printStackTrace();
}
String now = LocalDateTime.now().format(FORMATTER);
if (!now.equals(time)){
lock.writeLock().lock();
time = now;
value.set(config.getInitial());
lock.writeLock().unlock();
}
}
}
}
package com.league.idgenerate;
public class DefaultIdGeneratorConfig implements IdGeneratorConfig{
@Override
public String getSplitString() {
return "";
}
@Override
public int getInitial() {
return 1;
}
@Override
public String getPrefix() {
return "";
}
@Override
public int getRollingInterval() {
return 1;
}
}
測試類, 該類主要演示如何使用及相關測試功能代碼,如下:
package com.league.idgenerate;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.junit.Test;
/**
* 用法說明
* @author Ivan.Ma
*/
public class TestStandaloneIdGenerator {
@Test
public void test1(){
IdGenerator idGenerator = new DefaultIdGenerator();
System.out.println("--------簡單測試------------------");
for (int i=0; i<100; i++){
System.out.println(idGenerator.next());
}
}
@Test
public void test2(){
IdGenerator idGenerator = new DefaultIdGenerator();
//多線程測試
System.out.println("--------多線程測試不重復------------------");
Set idSet = Collections.synchronizedSet(new HashSet<>());
ExecutorService es = Executors.newFixedThreadPool(100);
for (int i=0; i<2000000; i++){
es.submit(() -> {
String val = idGenerator.next();
if (idSet.contains(val)){
System.out.println("重復了: " + val);
}else{
idSet.add(val);
}
});
}
es.shutdown();
System.out.println("啟用順序關閉");
while(true){
if(es.isTerminated()){
System.out.println("所有的子線程都結束了!");
break;
}
try {
System.out.println("子線程的任務還沒運行完");
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("共生成: " + idSet.size() + "個");
}
@Test
public void test3(){
//測試單機性能
System.out.println("--------測試單線程性能------------------");
IdGenerator idGenerator2 = new DefaultIdGenerator();
long t1 = System.currentTimeMillis();
int total = 10000000;
for (int i=0; i
idGenerator2.next();
}
System.out.println("單線程生成" + total + "個ID共耗時: " + (System.currentTimeMillis() - t1) + "ms");
}
//500個線程并發, 每個線程獲取10000個ID
@Test
public void test4(){
//測試多線程性能
System.out.println("--------測試多線程性能------------------");
ExecutorService es1 = Executors.newFixedThreadPool(500);
IdGenerator idGenerator3 = new DefaultIdGenerator();
long t1 = System.currentTimeMillis();
for (int i=0; i<500; i++){
es1.submit(() -> {
int count = 0;
while (count < 10000){
idGenerator3.next();
count++;
}
});
}
es1.shutdown();
System.out.println("啟用順序關閉");
while(true){
if(es1.isTerminated()){
System.out.println("所有的子線程都結束了!");
break;
}
try {
System.out.println("子線程的任務還沒運行完");
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("500線程,每個線程生成10000個序列號.共耗時: " + (System.currentTimeMillis() - t1) + " ms");
}
@Test
public void test5(){
System.out.println("--------測試生成的ID是否有時間滾動----------");
IdGenerator idGenerator = new DefaultIdGenerator();
for (int i=0; i<20; i++){
String id = idGenerator.next();
System.out.println(id);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
@Test
public void test6(){
System.out.println("--------ID生成器的特殊設置相關----------");
IdGeneratorConfig config = new DefaultIdGeneratorConfig() {
@Override
public String getSplitString() {
return "-";
}
@Override
public int getInitial() {
return 1000000;
}
@Override
public String getPrefix() {
return "NODE01";
}
};
IdGenerator idGenerator = new DefaultIdGenerator(config);
for (int i=0; i<20; i++){
String id = idGenerator.next();
System.out.println(id);
try {
Thread.sleep(1000 * 1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
運行結果如下:
--------簡單測試------------------
201602031124321
201602031124322
201602031124323
201602031124324
201602031124325
201602031124326
201602031124327
201602031124328
201602031124329
2016020311243210
2016020311243211
2016020311243212
2016020311243213
2016020311243214
2016020311243215
2016020311243216
2016020311243217
2016020311243218
2016020311243219
2016020311243220
2016020311243221
2016020311243222
2016020311243223
2016020311243224
2016020311243225
2016020311243226
2016020311243227
2016020311243228
2016020311243229
2016020311243230
2016020311243231
2016020311243232
2016020311243233
2016020311243234
2016020311243235
2016020311243236
2016020311243237
2016020311243238
2016020311243239
2016020311243240
2016020311243241
2016020311243242
2016020311243243
2016020311243244
2016020311243245
2016020311243246
2016020311243247
2016020311243248
2016020311243249
2016020311243250
2016020311243251
2016020311243252
2016020311243253
2016020311243254
2016020311243255
2016020311243256
2016020311243257
2016020311243258
2016020311243259
2016020311243260
2016020311243261
2016020311243262
2016020311243263
2016020311243264
2016020311243265
2016020311243266
2016020311243267
2016020311243268
2016020311243269
2016020311243270
2016020311243271
2016020311243272
2016020311243273
2016020311243274
2016020311243275
2016020311243276
2016020311243277
2016020311243278
2016020311243279
2016020311243280
2016020311243281
2016020311243282
2016020311243283
2016020311243284
2016020311243285
2016020311243286
2016020311243287
2016020311243288
2016020311243289
2016020311243290
2016020311243291
2016020311243292
2016020311243293
2016020311243294
2016020311243295
2016020311243296
2016020311243297
2016020311243298
2016020311243299
20160203112432100
--------多線程測試不重復------------------
啟用順序關閉
子線程的任務還沒運行完
子線程的任務還沒運行完
子線程的任務還沒運行完
子線程的任務還沒運行完
子線程的任務還沒運行完
所有的子線程都結束了!
共生成: 2000000個
--------測試單線程性能------------------
單線程生成10000000個ID共耗時: 1972ms
--------測試多線程性能------------------
啟用順序關閉
子線程的任務還沒運行完
子線程的任務還沒運行完
子線程的任務還沒運行完
子線程的任務還沒運行完
子線程的任務還沒運行完
子線程的任務還沒運行完
子線程的任務還沒運行完
所有的子線程都結束了!
500線程,每個線程生成10000個序列號.共耗時: 1605 ms
--------測試生成的ID是否有時間滾動----------
201602031124431
201602031124432
201602031124433
201602031124434
201602031124435
201602031124436
201602031124437
201602031124438
201602031124439
2016020311244310
2016020311244311
201602031124441
201602031124442
201602031124443
201602031124444
201602031124445
201602031124446
201602031124447
201602031124448
201602031124449
--------ID生成器的特殊設置相關----------
NODE01-20160203112445-1000000
NODE01-20160203112445-1000001
NODE01-20160203112446-1000000
NODE01-20160203112447-1000000
NODE01-20160203112448-1000000
NODE01-20160203112449-1000000
NODE01-20160203112450-1000000
NODE01-20160203112452-1000000
NODE01-20160203112453-1000000
NODE01-20160203112454-1000000
NODE01-20160203112455-1000000
NODE01-20160203112456-1000000
NODE01-20160203112457-1000000
NODE01-20160203112458-1000000
NODE01-20160203112459-1000000
NODE01-20160203112500-1000000
NODE01-20160203112501-1000000
NODE01-20160203112502-1000000
NODE01-20160203112503-1000000
NODE01-20160203112504-1000000
從該性能來看, 可以使用在高并發的場景, 歡迎大家來拍磚!
總結
以上是生活随笔為你收集整理的java 生成 序列号_Java并发编程-生成唯一序列号的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 模拟电子技术基础笔记(2)——半导体基础
- 下一篇: java取窗口句柄_如何获取Java中的