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没抢到商品

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

zookeeper实现商品秒杀抢购的更多相关文章

  1. 使用Redis中间件解决商品秒杀活动中出现的超卖问题(使用Java多线程模拟高并发环境)

    一.引入Jedis依赖 可以新建Spring或Maven工程,在pom文件中引入Jedis依赖: <dependency> <groupId>redis.clients< ...

  2. Java秒杀系统实战系列~商品秒杀代码实战

    摘要: 本篇博文是“Java秒杀系统实战系列文章”的第六篇,本篇博文我们将进入整个秒杀系统核心功能模块的代码开发,即“商品秒杀”功能模块的代码实战. 内容: “商品秒杀”功能模块是建立在“商品详情”功 ...

  3. PHP商品秒杀问题解决方案实例详解【mysql与redis】

    本文实例讲述了PHP商品秒杀问题解决方案.分享给大家供大家参考,具体如下: 引言 假设num是存储在数据库中的字段,保存了被秒杀产品的剩余数量. if($num > 0){ //用户抢购成功,记 ...

  4. php结合Redis实现高并发下的秒杀抢购功能

    实现思路 准备两个队列A和B,假设A队列的名称为stock,用于存放商品总库存信息,B队列的名称为users,用于存放抢购成功后的用户信息.每当有用户进行抢购操作时,先从A队列弹出一个元素,如果该元素 ...

  5. redis使用watch完成秒杀抢购功能

    Redis使用watch完成秒杀抢购功能: 使用redis中两个key完成秒杀抢购功能,mywatchkey用于存储抢购数量和mywatchlist用户存储抢购列表. 它的优点如下: 1. 首先选用内 ...

  6. redis使用watch完成秒杀抢购功能(转)

    redis使用watch完成秒杀抢购功能: 使用redis中两个key完成秒杀抢购功能,mywatchkey用于存储抢购数量和mywatchlist用户存储抢购列表. 它的优点如下: 1. 首先选用内 ...

  7. PHP商品秒杀计时实现(解决大流量方案)

    PHP商品秒杀功能我们多半以整点或时间点为例子,这样对于php来说处理不复杂,但有一个问题就是如果流量大要如何来处理,下面我们一起来看看解决办法. 要求要有小时分钟秒的实时倒计时的显示,用户端修改日期 ...

  8. redis使用watch完成秒杀抢购功能:

    redis使用watch完成秒杀抢购功能: 使用redis中两个key完成秒杀抢购功能,mywatchkey用于存储抢购数量和mywatchlist用户存储抢购列表. 它的优点如下: 1. 首先选用内 ...

  9. 01 整合IDEA+Maven+SSM框架的高并发的商品秒杀项目之业务分析与DAO层

    作者:nnngu 项目源代码:https://github.com/nnngu/nguSeckill 这是一个整合IDEA+Maven+SSM框架的高并发的商品秒杀项目.我们将分为以下几篇文章来进行详 ...

随机推荐

  1. light oj 1138 - Trailing Zeroes (III)【规律&&二分】

    1138 - Trailing Zeroes (III)   PDF (English) Statistics Forum Time Limit: 2 second(s) Memory Limit:  ...

  2. hdoj 2544 最短路【dijkstra or spfa】

    最短路 Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submis ...

  3. NSArray和NSMutableArray的详解

    数组中不能存放基本数据类型,必须存放对象,因此如果要存放基本数据类型,先进行NSTimer封装 NSArray的用法: 第一.初始化 NSArray *firstArray=[[NSArray all ...

  4. android最快的模拟器

    https://www.genymotion.com/ genymotion Genymotion是一套完整的工具,它提供了Android虚拟环境.它简直就是开发者.测试人员.推销者甚至是游戏玩家的福 ...

  5. Android内存中的图片

    图片在内存中的大小 Android.graphics.Bitmap类里有一个内部类Bitmap.Config类,在Bitmap类里createBitmap(intwidth, int height, ...

  6. 升级到tomcat7.0碰到的问题

    今天把tomcat从6.0.18升级到7.0.25,发现了两个问题 问题1 java.lang.ClassNotFoundException: org.apache.catalina.mbeans.S ...

  7. PowerShell中的数学计算

    Double类型和float都属于浮点类型,精度不高.而Decimal属于高精度

  8. mysql select 报错

    代码片段: sql_url = "select * from webpage where url = '%s'" % b try: cursor.execute(sql_url) ...

  9. JAVA线程全局异常处理

    大家平时写线程很多,但可能很少关注如何捕获线程的全局异常.其实jdk提供了两种捕获全局异常的方法,一种是基于整个线程类(staticsetDefaultUnaughtExceptionHandler( ...

  10. 理解 auto_ptr<T>

    1.auto_ptr<T>解决什么问题? 在堆上获取的资源,客户可能会忘记delete,或者由于异常没有执行到delete,导致资源泄漏.在栈上分配的对象,有个特点,不论出现什么情况,超出 ...