ConcurrentLinkedQueue并发抢票示例
在学习java并发的时候,在网上看了几个靠加锁方法块的方法来演示抢票的示例,运行起来还是要起并发冲突。后来看到一个用ConcurrentLinkedQueue(并发链接队列)来演示抢票的demo不错。然后我想在main最后末尾的时候打印各个并发线程实际抢票的总数,却始终看不到该显示出来的打印行。原来是main线程也参与了并发,打印行随机在中间位置。为了解决这个问题,可以使用CountDownLatch(倒计锁),等并发抢票线程都结束后,再接着运行main线程中后面的打印语句。
ConcurrentLinkedQueue的语义描述,可参考一下:
- A {@code ConcurrentLinkedQueue} is an appropriate choice when
- many threads will share access to a common collection.
- Like most other concurrent collection implementations, this class
- does not permit the use of {@code null} elements.
java示例demo
public class SellTicketQueue {
static Queue<String> tickets = new ConcurrentLinkedQueue<>();//1.初始化并发队列容器
static {
for (int i = 1; i <= 1000; i++) tickets.add("第" + i + "张票");//2.往容器中放1000张票
}
static HashMap<String, Integer> map = new HashMap<>();
final static CountDownLatch countDownLatch = new CountDownLatch(3);
public static void main(String[] args) {
for (int i = 0; i < 4; i++) { //3.开启多个线程抢票
new Thread(() -> {
while (true) {
String ticket = tickets.poll(); //4.一张张票出队列
if (ticket == null) break;
else System.out.println(Thread.currentThread().getName() + "销售--" + ticket);
Integer num = map.computeIfAbsent(Thread.currentThread().getName(), k -> 0);
num++;
map.put(Thread.currentThread().getName(), num);
}
countDownLatch.countDown();
}).start();
}
//5.以下代码实现在抢票线程完毕后,再打印各小计票数(保证打印在最末尾)
try {
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
for (Map.Entry<String, Integer> m : map.entrySet()) {
System.out.println(m.getKey() + " 总数 : " + m.getValue());
}
System.out.println("main thread is over ");
}
}
运行结果:这样看起来汇总小计直观一些。