java高并发下生成唯一订单号

java高并发下生成唯一订单号

天津交费系统需要生成订单号,对于订单号一定不能重复,尤其在高并发的情况下!

下面是在网上找的解决方案,目前我还没有解决问题的能力,只好拿来主义了。

解决方法一:基于锁

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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140

package cn.com.highset.util;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
* 订单号生成工具,生成非重复订单号,理论上限1毫秒1000个,可扩展
*
* @author JIE.ZHAO
* @date 2017年5月27日 下午3:47:30
*/
public class MakeOrderUtil {
/**
* 锁对象,可以为任意对象
*/
private static Object lockObj = "lockerOrder";
/**
* 订单号生成计数器
*/
private static long orderNumCount = 0L;
/**
* 每毫秒生成订单号数量最大值
*/
private static int maxPerMSECSize = 1000;

/**
* 生成非重复订单号,理论上限1毫秒1000个,可扩展
*
*/
public static String makeOrderNum() {
// 最终生成的订单号
String finOrderNum = "";
synchronized (lockObj) {
// 取系统当前时间作为订单号变量前半部分,精确到毫秒
long nowLong = Long.parseLong(new SimpleDateFormat(
"yyyyMMddHHmmssSSS").format(new Date()));
// 计数器到最大值归零,可扩展更大,目前1毫秒处理峰值1000个,1秒100万
if (orderNumCount >= maxPerMSECSize) {
orderNumCount = 0L;
}
// 组装订单号
String countStr = maxPerMSECSize + orderNumCount + "";
finOrderNum = nowLong + countStr.substring(1);
orderNumCount++;
}

return finOrderNum;
}

/**
* 生成非重复订单号,理论上限1毫秒1000个,可扩展
*
* @param tname
* 测试用
*/
public void makeOrderNum(String tname) {
try {
// 最终生成的订单号
String finOrderNum = "";
synchronized (lockObj) {
// 取系统当前时间作为订单号变量前半部分,精确到毫秒
long nowLong = Long.parseLong(new SimpleDateFormat(
"yyyyMMddHHmmssSSS").format(new Date()));
// 计数器到最大值归零,可扩展更大,目前1毫秒处理峰值1000个,1秒100万
if (orderNumCount >= maxPerMSECSize) {
orderNumCount = 0L;
}
// 组装订单号
String countStr = maxPerMSECSize + orderNumCount + "";
finOrderNum = nowLong + countStr.substring(1);
orderNumCount++;
System.out.println(finOrderNum + "--"
+ Thread.currentThread().getName() + "::" + tname);
// Thread.sleep(1000);
}
} catch (Exception e) {
e.printStackTrace();
}
}

/**
* 测试多线程调用订单号生成工具
*
* @author jie.Zhao
* @date 2017年5月27日 下午3:16:54
* @param args
*/
public static void main(String[] args) {
//
try {
for (int i = 0; i < 20; i++) {
Thread t1 = new Thread(new Runnable() {
public void run() {
MakeOrderUtil makeOrder = new MakeOrderUtil();
makeOrder.makeOrderNum("a");
}
}, "at" + i);
t1.start();

Thread t2 = new Thread(new Runnable() {
public void run() {
MakeOrderUtil makeOrder = new MakeOrderUtil();
makeOrder.makeOrderNum("b");
}
}, "bt" + i);
t2.start();
Thread t3 = new Thread(new Runnable() {
public void run() {
MakeOrderUtil makeOrder = new MakeOrderUtil();
makeOrder.makeOrderNum("b");
}
}, "bt" + i);
t3.start();
Thread t4 = new Thread(new Runnable() {
public void run() {
MakeOrderUtil makeOrder = new MakeOrderUtil();
makeOrder.makeOrderNum("b");
}
}, "bt" + i);
t4.start();
Thread t5 = new Thread(new Runnable() {
public void run() {
MakeOrderUtil makeOrder = new MakeOrderUtil();
makeOrder.makeOrderNum("b");
}
}, "bt" + i);
t5.start();
Thread t6 = new Thread(new Runnable() {
public void run() {
MakeOrderUtil makeOrder = new MakeOrderUtil();
makeOrder.makeOrderNum("b");
}
}, "bt" + i);
t6.start();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}

解决方法二:基于队列

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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
package cn.com.highset.util;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
/**
* 订单号生成工具,生成非重复订单号,理论上限1毫秒1000个,可扩展
* 基于队列
*
* @author JIE.ZHAO
* @date 2017年5月27日 下午4:11:12
*/
public class MakeOrderLinkedQueueUtil {
private static final ConcurrentLinkedQueue<Integer> queue = new ConcurrentLinkedQueue<Integer>();
private static final CountDownLatch latch = new CountDownLatch(1);
/**
* 每毫秒生成订单号数量最大值,约定取整百,整千。
*/
public static final int 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 makeOrderNum() {
long nowLong = Long.parseLong(new SimpleDateFormat("yyyyMMddHHmmssSSS")
.format(new Date()));
String number = maxPerMSECSize + poll() + "";
return nowLong + number.substring(1);
}

public static void main(String[] args) {
//
try {
for (int i = 0; i < 2000; i++) {
Thread t1 = new Thread(new Runnable() {
public void run() {
System.out.println(makeOrderNum());
}
}, "at" + i);
t1.start();

Thread t2 = new Thread(new Runnable() {
public void run() {
System.out.println(makeOrderNum());
}
}, "bt" + i);
t2.start();
Thread t3 = new Thread(new Runnable() {
public void run() {
System.out.println(makeOrderNum());
}
}, "bt" + i);
t3.start();
Thread t4 = new Thread(new Runnable() {
public void run() {
System.out.println(makeOrderNum());
}
}, "bt" + i);
t4.start();
Thread t5 = new Thread(new Runnable() {
public void run() {
System.out.println(makeOrderNum());
}
}, "bt" + i);
t5.start();
Thread t6 = new Thread(new Runnable() {
public void run() {
System.out.println(makeOrderNum());
}
}, "bt" + i);
t6.start();
}
} catch (Exception e) {
e.printStackTrace();
}

}
}

PS:2018年给自已一点时间去积累,去沉淀。。人不死总会出头。

-------------已经触及底线 感谢您的阅读-------------

本文标题:java高并发下生成唯一订单号

文章作者:趙小傑~~

发布时间:2017年05月27日 - 14:17:00

最后更新:2019年09月16日 - 19:34:10

原始链接:https://cnsyear.com/posts/55356351.html

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

0%