Java訂單號生成工具(實現二)基於佇列
阿新 • • 發佈:2019-01-25
使用了ConcurrentLinkedQueue,ConcurrentLinkedQueue是一個基於連結節點的無界執行緒安全佇列,它採用先進先出的規則對節點進行排序,當我們新增一個元素的時候,它會新增到佇列的尾部,當我們獲取一個元素時,它會返回佇列頭部的元素。它採用了“wait-free”演算法來實現,該演算法在Michael & Scott演算法上進行了一些修改, Michael & Scott演算法的詳細資訊可以參見參考資料一。
關於ConcurrentLinkedQueue詳情:http://ifeve.com/concurrentlinkedqueue/
package util;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import play.Configuration;
public class OrderNumberGenerator {
private static final ConcurrentLinkedQueue<Integer> queue = new ConcurrentLinkedQueue<Integer>();
private static final CountDownLatch latch = new CountDownLatch(1);
/**
* 每毫秒生成訂單號數量最大值,約定取整百,整千。
*/
public static final int maxPerMSECSize = Configuration.root().getInt("maxPerMSECSize", 1000);
private static void init() {
for (int i = 0; i < maxPerMSECSize; i++) {
queue.offer(i);
}
latch.countDown();
}
public static Integer poll() {
try {
if (latch.getCount() > 0) {
init();
latch.await(1, TimeUnit.SECONDS);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
Integer i = queue.poll();
queue.offer(i);
return i;
}
public static String get() {
long nowLong = Long.parseLong(new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date()));
String number = maxPerMSECSize + poll() + "";
return nowLong + number.substring(1);
}
}