队列处理订单号并发问题
1.背景
开发过程中会遇到一些有一定规则,但又不能重复的编号,例如订单号,一般会和日期关联,业务逻辑上,
一天内不会出现同样的订单号。处理这样的并发问题可以使用队列来完成。
2.ConcurrentLinkedQueue队列
这个demo中使用的是同步不限长队列ConcurrentLinkedQueue,在java.util.concurrent包下,具体API
可查看相关的文档。这里demo中主要使用它的offer()方法和poll()方法。
- offer()
向队列中插入(先进先出) - poll()
队列中取出并删除(先进先出)
3.代码实现
3.1 生成者
public class Producer implements Runnable{
private ConcurrentLinkedQueue<String> queue;
private int count=0;//计数,
public Producer(ConcurrentLinkedQueue<String> queue){
this.queue=queue;
}
@Override
public void run() {
while(true){
if(this.queue.isEmpty()){
for(int i = 0 ;i<10;i++){
int sum = count+i;
this.queue.offer(String.valueOf(sum));
}
count+=10;
}
}
}
}
这里使用isEmpty()方法,判断队列是否为空,实际生成环境场景,可能会设置一个最小值,具体的订单号生成的
业务逻辑都可以在此处添加。ps:size()方法,在数据较多的情况下,效率比isEmpty()低。
3.2监听启动线程
public class InitServlet extends ContextLoaderListener{
@Override
public void contextDestroyed(ServletContextEvent event) {
super.contextDestroyed(event);
}
@Override
public void contextInitialized(ServletContextEvent event) {
AttendanceServiceImpl as =
WebApplicationContextUtils.getWebApplicationContext(event
.getServletContext()).getBean(AttendanceServiceImpl.class);
Producer p = new Producer(as.getQueue());
new Thread(p).start();
System.out.println("intit=======================");
}
}
因为spring容器默认生成的bean是单例模式,所以这里可以直接将队列对象 放在service层对象上。
需要在web.xml中配置监听
<listener>
<listener-class>com.jshx.ktkq.init.InitServlet</listener-class>
</listener>
在接口中调用service对象 的方法获取队列中的值就行了。
**ConcurrentLinkedQueue的Demo
public class QueueTest {
public static void main(String[] args) {
ConcurrentLinkedQueue<Apple> queue = new ConcurrentLinkedQueue<>();
ExecutorService executor = Executors.newFixedThreadPool(11);
executor.submit(new Producer(queue));
for(int i=0;i<10;i++){
executor.submit(new Consumer(queue,String.valueOf(i)));
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
executor.shutdownNow();
}
//消费者
private static class Consumer implements Runnable{
private ConcurrentLinkedQueue<Apple> queue;
private String name;
public Consumer(ConcurrentLinkedQueue<Apple> queue,String name){
this.queue=queue;
this.name=name;
}
@Override
public void run() {
while(!this.queue.isEmpty()){
System.out.println(this.queue.poll()+"号苹果,被"+this.name+"消费");
}
}
}
//生成者
private static class Producer implements Runnable{
private int count=0;
private ConcurrentLinkedQueue<Apple> queue;
public Producer(ConcurrentLinkedQueue<Apple> queue){
this.queue=queue;
}
@Override
public void run() {
while(true){
if(this.queue.isEmpty()){
for(int i=0;i<10;i++){
int sum = this.count+i;
this.queue.offer(new Apple(String.valueOf(sum)));
}
this.count+=10;
}
}
}
}
private static class Apple{
private String name;
public Apple(String name){
this.name=name;
}
@Override
public String toString() {
return "Apple [name=" + name + "]";
}
}
}