多线程抢票_多线程抢票系统浅析

笔者打算写个轻量版的秒杀系统,那么需要多线程模拟客户去抢购某个商品。故有想先写一个简单的多线程抢票系统加深一下对线程池,同步的理解。

1.新建Java project,命名为ClientApp1, src文件夹里面新建demo文件夹。

项目结构如下,

2.程序模拟的场景用例如下,

多个线程模拟多个客户去购买春运车票

每个客户购买车票【0,9】,最少买0张,最多能买九张。

每个客户同步的买票,当某个线程在买票时,其他线程处于等待状态

所有客户线程买票完毕,主线程最后统计一共卖出多少张车票,切忌不能超卖。

CountDownLatch这个类使主线程等待其他线程各自执行完毕后再执行。

3.代码如下:

packagedemo;importjava.util.Random;importjava.util.concurrent.CountDownLatch;importorg.apache.log4j.Logger;public class Ticket implementsRunnable {private Integer capacity; //一共有多少张票

private Integer soldTickets = 0; //最后总计售出多少张票//CountDownLatch这个类使一个线程等待其他线程各自执行完毕后再执行。//是通过一个计数器来实现的,计数器的初始值是线程的数量。//每当一个线程执行完毕后,计数器的值就-1,当计数器的值为0时,表示所有线程都执行完毕,然后处于等待的线程就可以恢复工作了。

privateCountDownLatch latch;//使用Log4j2写日志

privateLogger log;public voidsetLog(Logger log) {this.log =log;

}publicTicket(Integer c, CountDownLatch latch) {//TODO Auto-generated constructor stub

this.capacity =c;this.latch =latch;

}publicInteger getSoldTickets() {returnsoldTickets;

}

@Overridepublic synchronized voidrun() {//每个线程客户购买0~9张票

int count = new Random().nextInt(10);

log.info(Thread.currentThread().getName()+ " wants to buy tickets : " +count);if(capacity >=count) {

capacity-=count;

soldTickets+=count;

log.info(Thread.currentThread().getName()+ " has bought tickets successfully. The left tikcets : " +capacity);

}else{

log.info(String.format("Insufficient tickets[%d], stop trading now.", capacity));

}

latch.countDown();

}

}

packagedemo;importjava.util.concurrent.CountDownLatch;importjava.util.concurrent.ExecutorService;importjava.util.concurrent.Executors;importjava.util.concurrent.LinkedBlockingQueue;importjava.util.concurrent.ThreadPoolExecutor;importjava.util.concurrent.TimeUnit;importorg.apache.log4j.LogManager;importorg.apache.log4j.Logger;public classTicketPractice {private staticExecutorService pool;private staticCountDownLatch latch;private static Integer NUMBER = 5000; //客户线程数目

private static final Logger logger = LogManager.getLogger(TicketPractice.class);public static voidmain(String[] args) {//TODO Auto-generated method stub

pool = new ThreadPoolExecutor(100, NUMBER, 300, TimeUnit.SECONDS,new LinkedBlockingQueue(NUMBER),Executors.defaultThreadFactory(),newThreadPoolExecutor.AbortPolicy());

latch= newCountDownLatch(NUMBER);

Ticket task= newTicket(NUMBER, latch);

task.setLog(logger);for(int i=0;i

pool.execute(task);

}try{

latch.await();

}catch(InterruptedException e) {//TODO Auto-generated catch block

e.printStackTrace();

}

logger.info("+++++++++++++++++++++++++++++++++++");

logger.info("Sold tickets in total : " +task.getSoldTickets());

logger.info("+++++++++++++++++++++++++++++++++++");

}

}

4.值得一提的是,如使用Log4j2,需要引入外部三个jar包

log4j-1.2-api-2.12.1.jar

log4j-api-2.12.1.jar

log4j-core-2.12.1.jar

Log4j2.xml内容如下,

5.运行程序,5000个客户线程随机买票,总票数5000张,不能超卖。程序运行日志如下,

22:11:10.317 INFO demo.Ticket 37 run - pool-2-thread-1 wants to buy tickets : 0

22:11:10.322 INFO demo.Ticket 41 run - pool-2-thread-1 has bought tickets successfully. The left tikcets : 5000

22:11:10.322 INFO demo.Ticket 37 run - pool-2-thread-100 wants to buy tickets : 6

22:11:10.322 INFO demo.Ticket 41 run - pool-2-thread-100 has bought tickets successfully. The left tikcets : 4994

22:11:10.323 INFO demo.Ticket 37 run - pool-2-thread-99 wants to buy tickets : 5

22:11:10.323 INFO demo.Ticket 41 run - pool-2-thread-99 has bought tickets successfully. The left tikcets : 4989

。。。。。。

。。。。。。

22:11:11.359 INFO demo.Ticket 37 run - pool-2-thread-3 wants to buy tickets : 2

22:11:11.359 INFO demo.Ticket 44 run - Insufficient tickets[0], stop trading now.

22:11:11.365 INFO demo.TicketPractice 38 main - +++++++++++++++++++++++++++++++++++

22:11:11.366 INFO demo.TicketPractice 39 main - Sold tickets in total : 5000

22:11:11.366 INFO demo.TicketPractice 40 main - +++++++++++++++++++++++++++++++++++

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值