专注于 JetBrains IDEA 全家桶,永久激活,教程
持续更新 PyCharm,IDEA,WebStorm,PhpStorm,DataGrip,RubyMine,CLion,AppCode 永久激活教程

java模拟多线程并发购票业务

模拟多线程并发购票系统编程

1、数据表

CREATE TABLE `t_ticket` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '表id',
  `ticket_count` int(10) NOT NULL DEFAULT '0' COMMENT '票数量',
  `type` varchar(15) DEFAULT NULL COMMENT '票类型',
  `version` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '版本号',
  PRIMARY KEY (`id`),
  KEY `index_type` (`type`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `t_ticket` (`id`, `ticket_count`, `type`, `version`) VALUES ('1', '200', 'movie', '40');

2、售票扣减票数sql

先执行for update锁住数据库操作的行,再执行更新操作,更新操作加版本号

<select id="selectByTypeForUpdate" resultMap="BaseResultMap" parameterType="java.lang.String">
    select
    <include refid="Base_Column_List"/>
    from t_ticket
    where type = #{type,jdbcType=VARCHAR} for update
</select>
<update id="updateTicketSale" parameterType="com.example.ticket.demo.model.table.Ticket">
    update t_ticket
    <set>
        version = ${version} + 1,
        <if test="ticketCount != null">
            ticket_count = #{ticketCount,jdbcType=INTEGER}
        </if>
    </set>
    where ticket_count > 0 and version = #{version,jdbcType=INTEGER} and id = #{id,jdbcType=INTEGER}
</update>

3、数据库操作业务代码

@Transactional
@Override
public int updateTicketSale(Ticket record) {
    Ticket t = ticketMapper.selectByTypeForUpdate(record.getType());
    if (t.getTicketCount() > 0) {
        record.setVersion(t.getVersion());
        return ticketMapper.updateTicketSale(record);
    }
    return 0;
}

4、售票扣减数量代码

@Slf4j
public class TicketSaleManager {

    private static ITicketService ticketService;
    //要确保tickCount只有一个实例
    public static volatile int tickCount;

    public TicketSaleManager() {
        if (ticketService == null){
            ticketService = SpringUtils.getBean("ticketService");
        }
    }

    public void saleTicket(String salerName, int saleCount) {
        synchronized (TicketSaleManager.class) {
            Ticket ticket = ticketService.selectByType("movie");
            tickCount = ticket.getTicketCount();
            try {
                if (tickCount > 0) {
                    if (saleCount > tickCount) {
                        saleCount = tickCount;
                    }
                    log.info(salerName + ": 售出" + saleCount + "张票。");
                    tickCount = tickCount - saleCount;

                    Ticket record = new Ticket();
                    record.setId(ticket.getId());
                    record.setTicketCount(tickCount);
                    record.setType("movie");
                    ticketService.updateTicketSale(record);
                    log.info(">>>剩下" + tickCount + "张票。");
                } else {
                    log.info(">>>票已被售完。");
                }
            } catch (Exception e) {
                log.error("sale Exception", e);
            }
        }
    }
}

5、创建执行售票线程

class TicketSaleThread implements Runnable {
    private String salerName;// 售票员姓名
    private int saleCount;//售票数量
    public TicketSaleThread(String salerName, int saleCount) {
        this.salerName = salerName;
        this.saleCount = saleCount;
    }
    @Override
    public void run() {
        new TicketSaleManager().saleTicket(salerName, saleCount);
    }
}

6、模拟多窗口多线程售票

@Test
public void test() throws InterruptedException {
    int windowCount = 6;//售票窗口数量
    ExecutorService executorService = Executors.newFixedThreadPool(windowCount);
    for (int i = 0; i < 10000; i++) {
        windowCount = windowCount < 1? 4: windowCount;
        int saleCount = (int) (Math.random() * 10.0d);//saleCount售票数量
        saleCount = saleCount < 1 ? 1 : saleCount;
        TicketSaleThread threadDemo = new TicketSaleThread(">>>售票窗口:" + windowCount, saleCount);
        executorService.execute(threadDemo);
        windowCount--;
    }
    Thread.sleep(10000L);
    executorService.shutdown();
}

代码(待完善):https://gitee.com/lion123/springboot-thread-demo

文章永久链接:https://tech.souyunku.com/25006

未经允许不得转载:搜云库技术团队 » java模拟多线程并发购票业务

JetBrains 全家桶,激活、破解、教程

提供 JetBrains 全家桶激活码、注册码、破解补丁下载及详细激活教程,支持 IntelliJ IDEA、PyCharm、WebStorm 等工具的永久激活。无论是破解教程,还是最新激活码,均可免费获得,帮助开发者解决常见激活问题,确保轻松破解并快速使用 JetBrains 软件。获取免费的破解补丁和激活码,快速解决激活难题,全面覆盖 2024/2025 版本!

联系我们联系我们