最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

基于ZooKeeper實現(xiàn)隊列源碼

 更新時間:2017年09月18日 15:43:17   作者:MassiveStars  
這篇文章主要介紹了基于ZooKeeper實現(xiàn)隊列源碼的相關內(nèi)容,包括其實現(xiàn)原理和應用場景,以及對隊列的簡單介紹,具有一定參考價值,需要的朋友可以了解下。

實現(xiàn)原理

先進先出隊列是最常用的隊列,使用Zookeeper實現(xiàn)先進先出隊列就是在特定的目錄下創(chuàng)建PERSISTENT_EQUENTIAL節(jié)點,創(chuàng)建成功時Watcher通知等待的隊列,隊列刪除序列號最小的節(jié)點用以消費。此場景下Zookeeper的znode用于消息存儲,znode存儲的數(shù)據(jù)就是消息隊列中的消息內(nèi)容,SEQUENTIAL序列號就是消息的編號,按序取出即可。由于創(chuàng)建的節(jié)點是持久化的,所以不必擔心隊列消息的丟失問題。

隊列(Queue)

分布式隊列是通用的數(shù)據(jù)結(jié)構(gòu),為了在 Zookeeper 中實現(xiàn)分布式隊列,首先需要指定一個 Znode 節(jié)點作為隊列節(jié)點(queue node), 各個分布式客戶端通過調(diào)用 create() 函數(shù)向隊列中放入數(shù)據(jù),調(diào)用create()時節(jié)點路徑名帶"qn-"結(jié)尾,并設置順序(sequence)節(jié)點標志。 由于設置了節(jié)點的順序標志,新的路徑名具有以下字符串模式:"_path-to-queue-node_/qn-X",X 是唯一自增號。需要從隊列中獲取數(shù)據(jù)/移除數(shù)據(jù)的客戶端首先調(diào)用 getChildren() 函數(shù),有數(shù)據(jù)則獲?。ǐ@取數(shù)據(jù)后可以刪除也可以不刪),沒有則在隊列節(jié)點(queue node)上將 watch 設置為 true,等待觸發(fā)并處理最小序號的節(jié)點(即從序號最小的節(jié)點中取數(shù)據(jù))。

應用場景

Zookeeper隊列不太適合要求高性能的場合,但可以在數(shù)據(jù)量不大的情況下考慮使用。比如已在項目中使用Zookeeper又需要小規(guī)模的隊列應用,這時可以使用Zookeeper實現(xiàn)的隊列;畢竟引進一個消息中間件會增加系統(tǒng)的復雜性和運維的壓力。

詳細代碼

ZookeeperClient工具類

package org.massive.common; 
import org.apache.zookeeper.WatchedEvent; 
import org.apache.zookeeper.Watcher; 
import org.apache.zookeeper.ZooKeeper; 
import java.io.IOException; 
import java.util.concurrent.CountDownLatch; 
import java.util.concurrent.TimeUnit; 
/** 
 * Created by Massive on 2016/12/18. 
 */ 
public class ZooKeeperClient { 
 private static String connectionString = "localhost:2181"; 
 private static int sessionTimeout = 10000; 
 public static ZooKeeper getInstance() throws IOException, InterruptedException { 
 //-------------------------------------------------------------- 
 // 為避免連接還未完成就執(zhí)行zookeeper的get/create/exists操作引起的(KeeperErrorCode = ConnectionLoss) 
 // 這里等Zookeeper的連接完成才返回實例 
 //-------------------------------------------------------------- 
 final CountDownLatch connectedSignal = new CountDownLatch(1); 
 ZooKeeper zk = new ZooKeeper(connectionString, sessionTimeout, new Watcher() { 
  @Override 
  public void process(WatchedEvent event) { 
   if (event.getState() == Event.KeeperState.SyncConnected) { 
   connectedSignal.countDown(); 
   } else if (event.getState() == Event.KeeperState.Expired) { 
   } 
  } 
  }); 
 connectedSignal.await(sessionTimeout, TimeUnit.MILLISECONDS); 
 return zk; 
 } 
 public static int getSessionTimeout() { 
 return sessionTimeout; 
 } 
 public static void setSessionTimeout(int sessionTimeout) { 
 ZooKeeperClient.sessionTimeout = sessionTimeout; 
 } 
}

ZooKeeperQueue

package org.massive.queue; 
import org.apache.commons.lang3.RandomUtils; 
import org.apache.zookeeper.*; 
import org.apache.zookeeper.data.Stat; 
import org.massive.common.ZooKeeperClient; 
import java.io.IOException; 
import java.io.UnsupportedEncodingException; 
import java.util.List; 
import java.util.SortedSet; 
import java.util.TreeSet; 
/** 
 * Created by Allen on 2016/12/22. 
 */ 
public class ZooKeeperQueue { 
 private ZooKeeper zk; 
 private int sessionTimeout; 
 private static byte[] ROOT_QUEUE_DATA = {0x12,0x34}; 
 private static String QUEUE_ROOT = "/QUEUE"; 
 private String queueName; 
 private String queuePath; 
 private Object mutex = new Object(); 
 public ZooKeeperQueue(String queueName) throws IOException, KeeperException, InterruptedException { 
 this.queueName = queueName; 
 this.queuePath = QUEUE_ROOT + "/" + queueName; 
 this.zk = ZooKeeperClient.getInstance(); 
 this.sessionTimeout = zk.getSessionTimeout(); 
 //---------------------------------------------------- 
 // 確保隊列根目錄/QUEUE和當前隊列的目錄的存在 
 //---------------------------------------------------- 
 ensureExists(QUEUE_ROOT); 
 ensureExists(queuePath); 
 } 
 public byte[] consume() throws InterruptedException, KeeperException, UnsupportedEncodingException { 
 List<String> nodes = null; 
 byte[] returnVal = null; 
 Stat stat = null; 
 do { 
  synchronized (mutex) { 
  nodes = zk.getChildren(queuePath, new ProduceWatcher()); 
  //---------------------------------------------------- 
  // 如果沒有消息節(jié)點,等待生產(chǎn)者的通知 
  //---------------------------------------------------- 
  if (nodes == null || nodes.size() == 0) { 
   mutex.wait(); 
  } else { 
   SortedSet<String> sortedNode = new TreeSet<String>(); 
   for (String node : nodes) { 
   sortedNode.add(queuePath + "/" + node); 
   } 
   //---------------------------------------------------- 
   // 消費隊列里序列號最小的消息 
   //---------------------------------------------------- 
   String first = sortedNode.first(); 
   returnVal = zk.getData(first, false, stat); 
   zk.delete(first, -1); 
   System.out.print(Thread.currentThread().getName() + " "); 
   System.out.print("consume a message from queue:" + first); 
   System.out.println(", message data is: " + new String(returnVal,"UTF-8")); 
   return returnVal; 
  } 
  } 
 } while (true); 
 } 
 class ProduceWatcher implements Watcher { 
 @Override 
 public void process(WatchedEvent event) { 
  //---------------------------------------------------- 
  // 生產(chǎn)一條消息成功后通知一個等待線程 
  //---------------------------------------------------- 
  synchronized (mutex) { 
  mutex.notify(); 
  } 
 } 
 } 
 public void produce(byte[] data) throws KeeperException, InterruptedException, UnsupportedEncodingException { 
 //---------------------------------------------------- 
 // 確保當前隊列目錄存在 
 // example: /QUEUE/queueName 
 //---------------------------------------------------- 
 ensureExists(queuePath); 
 String node = zk.create(queuePath + "/", data, 
  ZooDefs.Ids.OPEN_ACL_UNSAFE, 
  CreateMode.PERSISTENT_SEQUENTIAL); 
 System.out.print(Thread.currentThread().getName() + " "); 
 System.out.print("produce a message to queue:" + node); 
 System.out.println(" , message data is: " + new String(data,"UTF-8")); 
 } 
 public void ensureExists(String path) { 
 try { 
  Stat stat = zk.exists(path, false); 
  if (stat == null) { 
  zk.create(path, ROOT_QUEUE_DATA, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); 
  } 
 } catch (KeeperException e) { 
  e.printStackTrace(); 
 } catch (InterruptedException e) { 
  e.printStackTrace(); 
 } 
 } 
 public static void main(String[] args) throws IOException, InterruptedException, KeeperException { 
 String queueName = "test"; 
 final ZooKeeperQueue queue = new ZooKeeperQueue(queueName); 
 for (int i = 0; i < 10; i++) { 
  new Thread(new Runnable() { 
  @Override 
  public void run() { 
   try { 
   queue.consume(); 
   System.out.println("--------------------------------------------------------"); 
   System.out.println(); 
   } catch (InterruptedException e) { 
   e.printStackTrace(); 
   } catch (KeeperException e) { 
   e.printStackTrace(); 
   } catch (UnsupportedEncodingException e) { 
   e.printStackTrace(); 
   } 
  } 
  }).start(); 
 } 
 new Thread(new Runnable() { 
  @Override 
  public void run() { 
  for (int i = 0; i < 10; i++) { 
   try { 
   Thread.sleep(RandomUtils.nextInt(100 * i, 200 * i)); 
   queue.produce(("massive" + i).getBytes()); 
   } catch (InterruptedException e) { 
   e.printStackTrace(); 
   } catch (KeeperException e) { 
   e.printStackTrace(); 
   } catch (UnsupportedEncodingException e) { 
   e.printStackTrace(); 
   } 
  } 
  } 
 },"Produce-thread").start(); 
 } 
}

測試

運行main方法,本機器的某次輸出結(jié)果

Produce-thread produce a message to queue:/QUEUE/test/0000000000 , message data is: massive0 
Thread-8 consume a message from queue:/QUEUE/test/0000000000, message data is: massive0 
-------------------------------------------------------- 
Produce-thread produce a message to queue:/QUEUE/test/0000000001 , message data is: massive1 
Thread-6 consume a message from queue:/QUEUE/test/0000000001, message data is: massive1 
-------------------------------------------------------- 
Produce-thread produce a message to queue:/QUEUE/test/0000000002 , message data is: massive2 
Thread-3 consume a message from queue:/QUEUE/test/0000000002, message data is: massive2 
-------------------------------------------------------- 
Produce-thread produce a message to queue:/QUEUE/test/0000000003 , message data is: massive3 
Thread-0 consume a message from queue:/QUEUE/test/0000000003, message data is: massive3 
-------------------------------------------------------- 
Produce-thread produce a message to queue:/QUEUE/test/0000000004 , message data is: massive4 
Thread-5 consume a message from queue:/QUEUE/test/0000000004, message data is: massive4 
-------------------------------------------------------- 
Produce-thread produce a message to queue:/QUEUE/test/0000000005 , message data is: massive5 
Thread-2 consume a message from queue:/QUEUE/test/0000000005, message data is: massive5 
-------------------------------------------------------- 
Produce-thread produce a message to queue:/QUEUE/test/0000000006 , message data is: massive6 
Thread-4 consume a message from queue:/QUEUE/test/0000000006, message data is: massive6 
-------------------------------------------------------- 
Produce-thread produce a message to queue:/QUEUE/test/0000000007 , message data is: massive7 
Thread-9 consume a message from queue:/QUEUE/test/0000000007, message data is: massive7 
-------------------------------------------------------- 
Produce-thread produce a message to queue:/QUEUE/test/0000000008 , message data is: massive8 
Thread-7 consume a message from queue:/QUEUE/test/0000000008, message data is: massive8 
-------------------------------------------------------- 
Produce-thread produce a message to queue:/QUEUE/test/0000000009 , message data is: massive9 
Thread-1 consume a message from queue:/QUEUE/test/0000000009, message data is: massive9 

總結(jié)

以上就是本文有關于隊列和基于ZooKeeper實現(xiàn)隊列源碼介紹的全部內(nèi)容,希望對大家有所幫助。

感謝朋友們對本站的支持!

相關文章

  • springboot項目整合注冊功能模塊開發(fā)實戰(zhàn)

    springboot項目整合注冊功能模塊開發(fā)實戰(zhàn)

    這篇文章主要介紹了springboot項目整合注冊功能模塊開發(fā)實戰(zhàn),在用戶的注冊是首先需要查詢當前的用戶名是否存在,如果存在則不能進行注冊,相當于一個查詢語句,本文通過實例代碼詳細講解,需要的朋友可以參考下
    2022-11-11
  • springboot默認文件緩存(easy-captcha?驗證碼)

    springboot默認文件緩存(easy-captcha?驗證碼)

    這篇文章主要介紹了springboot的文件緩存(easy-captcha?驗證碼),本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-06-06
  • Java Lambda表達式原理及多線程實現(xiàn)

    Java Lambda表達式原理及多線程實現(xiàn)

    這篇文章主要介紹了Java Lambda表達式原理及多線程實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-07-07
  • mybatis設置sql執(zhí)行時間超時時間的方法

    mybatis設置sql執(zhí)行時間超時時間的方法

    本文主要介紹了mybatis設置sql執(zhí)行時間超時時間的方法,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • 詳談spring中bean注入無效和new創(chuàng)建對象的區(qū)別

    詳談spring中bean注入無效和new創(chuàng)建對象的區(qū)別

    這篇文章主要介紹了spring中bean注入無效和new創(chuàng)建對象的區(qū)別,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-02-02
  • IntelliJ IDEA 2021.1 EAP 1 發(fā)布支持 Java 16 和 WSL 2

    IntelliJ IDEA 2021.1 EAP 1 發(fā)布支持 Java 16 和 WSL 2

    這篇文章主要介紹了IntelliJ IDEA 2021.1 EAP 1 發(fā)布支持 Java 16 和 WSL 2,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-02-02
  • Spring事務中的事務傳播行為使用方式詳解

    Spring事務中的事務傳播行為使用方式詳解

    Spring框架作為一個輕量級的開源框架,在企業(yè)應用開發(fā)中被廣泛使用,在Spring事務管理中,事務傳播行為是非常重要的一部分,它定義了方法如何參與到已經(jīng)存在的事務中或者如何開啟新的事務,本文將詳細介紹Spring事務中的幾種事務傳播行為,詳細講解具體使用方法
    2023-06-06
  • Mybatis中如何使用sum對字段求和

    Mybatis中如何使用sum對字段求和

    這篇文章主要介紹了Mybatis中如何使用sum對字段求和,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-01-01
  • IntelliJ IDEA中Scala、sbt、maven配置教程

    IntelliJ IDEA中Scala、sbt、maven配置教程

    這篇文章主要介紹了IntelliJ IDEA中Scala、sbt、maven配置教程,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-09-09
  • Java中Integer方法實例詳解

    Java中Integer方法實例詳解

    這篇文章主要給大家介紹了關于Java中Integer方法的相關資料,Java中的Integer是int的包裝類型,文中通過代碼實例介紹的非常詳細,需要的朋友可以參考下
    2023-08-08

最新評論

福贡县| 绥德县| 明溪县| 沂源县| 恩施市| 佛冈县| 城固县| 崇州市| 远安县| 安义县| 虹口区| 孟连| 涿州市| 精河县| 宁蒗| 勐海县| 开封市| 芜湖市| 乐都县| 含山县| 吉隆县| 元谋县| 德清县| 乃东县| 根河市| 慈利县| 榆中县| 泰州市| 普安县| 武清区| 长泰县| 浏阳市| 宝鸡市| 铜山县| 金溪县| 渝北区| 类乌齐县| 邹城市| 朝阳市| 海盐县| 始兴县|