zoukankan      html  css  js  c++  java
  • zookeeper实现商品秒杀抢购

    package com.test;
    
    import java.io.IOException;
    import java.util.List;
    import java.util.concurrent.CyclicBarrier;
    
    import org.apache.zookeeper.CreateMode;
    import org.apache.zookeeper.KeeperException;
    import org.apache.zookeeper.WatchedEvent;
    import org.apache.zookeeper.Watcher;
    import org.apache.zookeeper.Watcher.Event.EventType;
    import org.apache.zookeeper.ZooDefs.Ids;
    import org.apache.zookeeper.ZooKeeper;
    import org.apache.zookeeper.data.Stat;
    
    public class Main {
    
        public static void main(String[] args) throws IOException, KeeperException, InterruptedException {
    
            ZooKeeper zk = new ZooKeeper("127.0.0.1", 2000, null);
            Stat st = zk.exists("/goods", false);
            if (st == null) {
                zk.create("/goods", new byte[0], Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
            }
            String[] goods = { "iPhone6s", "小米移动电源" };
            for (String g : goods) {
                zk.create("/goods/" + g, new byte[0], Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
            }
    
            int threadCount = 5;
            CyclicBarrier cb = new CyclicBarrier(threadCount); // 为了更好地表示并发,这里用了CyclicBarrier类
            for (int i = 0; i < threadCount; i++) {
                // 用多线程摸您多用户
                new Thread(new Thread1(cb)).start();
            }
            System.in.read();
    
        }
    
        static class Thread1 implements Runnable {
            ZooKeeper zk = null;
            CyclicBarrier cb;
    
            // 是否还没有抢过商品
            boolean isNotGet = true;
    
            public Thread1(CyclicBarrier cb) {
                this.cb = cb;
            }
    
            private void snatchGoods() throws Exception {
    
                // 获取商品库存
                List<String> goodsList = zk.getChildren("/goods", true);// 获取商品列表并监控变化,如果在和其它用户抢购同一个商品时没抢到的情况下可再次监控其它商品
                if (goodsList.isEmpty()) {
                    // 商品库存为空,表示商品抢光了
                    System.out.println(Thread.currentThread().getName() + "没抢到商品");
                } else {
                    // 获取第一个商品
                    String goods = goodsList.get(0);
                    try {
                        // 从内存中删除商品节点,表示抢购,如果删除失败,就表示没抢到这个商品,并进入到下面的catch块中
                        zk.delete("/goods/" + goods, -1);
                        // 限制每个用户只能抢购一件商品,设置false表示已经抢购过了
                        isNotGet = false;
                        System.out.println(Thread.currentThread().getName() + "抢到了" + goods);
                    } catch (Exception e) {
    
                    }
                }
            }
    
            @Override
            public void run() {
                try {
                    zk = new ZooKeeper("127.0.0.1:2181", 2000, new Watcher() {
                        @Override
                        public void process(WatchedEvent event) {
                            try {
                                EventType type = event.getType();
                                if (isNotGet) {
                                    if (type == EventType.None) {
                                        // 用户第一次访问,则立即执行商品的抢购
                                        snatchGoods();
                                    } else if (type == EventType.NodeChildrenChanged) {
                                        // 抢购一件商品失败后,再抢购另一件商品
                                        snatchGoods();
                                    }
                                }
                            } catch (Exception e) {
                                System.out.println(e.getMessage());
                            }
                        }
                    });
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
    1. 使用多线程模拟多用户抢购
    2. 用户第一次访问,则立即执行商品的抢购
    3. 抢购一件商品失败后,再抢购另一件商品
    4. 商品库存为空,表示商品抢光了

    zookeeper实现商品秒杀抢购:

    秒杀活动是一些购物平台推出的集中人气的活动,一般商品数量很少,价格很便宜,限定开始购买的时间,会在以秒为单位的时间内被购买一空。比如原价千元甚至万元的商品以一元的价格出售,但数量只有一件,在某天的某个时间开始出售,这就造成很多人去抢这一件商品。

    获取商品列表并监控变化,如果在和其它用户抢购同一个商品时没抢到的情况下可再次监控其它商品

    抢购一件商品失败后,再抢购另一件商品

    运行多次,打印出如下结果:

    Thread-4-EventThread抢到了iPhone6s
    Thread-1-EventThread抢到了小米移动电源
    Thread-2-EventThread没抢到商品
    Thread-3-EventThread没抢到商品
    Thread-0-EventThread没抢到商品


    Thread-3-EventThread抢到了iPhone6s
    Thread-2-EventThread抢到了小米移动电源
    Thread-4-EventThread没抢到商品
    Thread-1-EventThread没抢到商品
    Thread-0-EventThread没抢到商品


    Thread-0-EventThread抢到了iPhone6s
    Thread-3-EventThread抢到了小米移动电源
    Thread-4-EventThread没抢到商品
    Thread-2-EventThread没抢到商品
    Thread-1-EventThread没抢到商品


    Thread-2-EventThread抢到了iPhone6s
    Thread-4-EventThread抢到了小米移动电源
    Thread-0-EventThread没抢到商品
    Thread-3-EventThread没抢到商品
    Thread-1-EventThread没抢到商品

    可以看到,两件商品,多个线程并发抢购,总是只有两个线程分别抢到不同的商品。

  • 相关阅读:
    [原]关于在Python和C#之间消息传递的问题
    【原】为DevExpress的ChartControl添加Y轴控制 和 GridControl中指定列添加超级链接
    【原】使用Json作为Python和C#混合编程时对象转换的中间文件
    【原】在Matplotlib绘图中添加Latex风格公式
    【原】关于AdaBoost的一些再思考
    【原】使用Tkinter绘制GUI并结合Matplotlib实现交互式绘图
    使用C#+Linq+SQL快速开发业务
    oracle expdp导出时报 ora-39070:无法打开日志文件
    Oracle 关于expdp和impdp的应用实践
    IIS7启动优化
  • 原文地址:https://www.cnblogs.com/itbole/p/5286314.html
Copyright © 2011-2022 走看看