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(); } } } }
zookeeper實現商品秒殺搶購:java
秒殺活動是一些購物平臺推出的集中人氣的活動,通常商品數量不多,價格很便宜,限定開始購買的時間,會在以秒爲單位的時間內被購買一空。好比原價千元甚至萬元的商品以一元的價格出售,但數量只有一件,在某天的某個時間開始出售,這就形成不少人去搶這一件商品。apache
獲取商品列表並監控變化,若是在和其它用戶搶購同一個商品時沒搶到的狀況下可再次監控其它商品多線程
搶購一件商品失敗後,再搶購另外一件商品併發
運行屢次,打印出以下結果:ide
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沒搶到商品
能夠看到,兩件商品,多個線程併發搶購,老是隻有兩個線程分別搶到不一樣的商品。this