起因
朋友在点饮品时候,看到等号的大屏发现门店的单号是和门店的产品售卖情况强相关的,根据单号就可以看到一个门店当日的营业额情况。这样的单号生成方式和早起网站用户ID自增生成一样,虽然企业在外宣传自己有xx亿用户,但注册一个新用户看一下用户ID就完全暴露了。
按朋友的思路写的一个单号生成器
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
|
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;
import lombok.SneakyThrows;
/**
* 按分秒生成票据,每秒生成9个,只能获取当前时间的票据
*
* @author p_x_c
*/
public class TicketGenerator {
private static final int MAX_TICKETS_PER_SECOND = 9;
private static final int TIMEOUT_SECONDS = 5;
private final BlockingQueue<String> ticketQueue = new ArrayBlockingQueue<>(MAX_TICKETS_PER_SECOND);
private final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("mmss");
public TicketGenerator() {
Thread generatorThread = new Thread(() -> {
while (true) {
try {
LocalDateTime now = LocalDateTime.now();
String timePrefix = now.format(FORMATTER);
for (int i = 1; i <= MAX_TICKETS_PER_SECOND; i++) {
String ticket = String.format("%s%01d", timePrefix, i);
ticketQueue.put(ticket);
}
// Sleep for one second before generating new tickets
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread()
.interrupt();
break;
}
}
});
generatorThread.setDaemon(true);
generatorThread.start();
}
@SneakyThrows
public static void main(String[] args) {
TicketGenerator ticketGenerator = new TicketGenerator();
// Example usage
for (int i = 0; i < 20; i++) {
String ticket = ticketGenerator.getTicket();
System.out.println("Got ticket: " + ticket);
Thread.sleep(10); // Simulate some delay between requests
}
}
@SneakyThrows
public String getTicket() {
LocalDateTime startTime = LocalDateTime.now();
while (true) {
String ticket = ticketQueue.poll(1, TimeUnit.SECONDS);
if (ticket == null) {
if (LocalDateTime.now()
.isAfter(startTime.plusSeconds(TIMEOUT_SECONDS))) {
return "-1"; // Return -1 if timeout
}
continue;
}
// Check if the ticket matches the current time
String currentPrefix = LocalDateTime.now()
.format(FORMATTER);
if (ticket.startsWith(currentPrefix)) {
return ticket;
}
}
}
}
|