<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Storm常見模式——TimeCacheMap

      Storm中使用一種叫做TimeCacheMap的數據結構,用于在內存中保存近期活躍的對象,它的實現非常地高效,而且可以自動刪除過期不再活躍的對象。

      TimeCacheMap使用多個桶buckets來縮小鎖的粒度,以此換取高并發讀寫性能。下面我們來看看TimeCacheMap內部是如何實現的。

      1. 實現原理

      桶鏈表:鏈表中每個元素是一個HashMap,用于保存key,value格式的數據。

          private LinkedList<HashMap<K, V>> _buckets;

      鎖對象:用于對TimeCacheMap進行get/put等操作時上鎖保證原子性。

          private final Object _lock = new Object();

      后臺清理線程:負責超時后清理數據。

          private Thread _cleaner;

      超時回調接口:用于超時后進行函數回調,做一些其他處理。

          public static interface ExpiredCallback<K, V> {
              public void expire(K key, V val);
          }
          private ExpiredCallback _callback;

      有了以上數據結構,下面來看看構造函數的具體實現:

      1、 首先,初始化指定個數的bucket,以鏈式鏈表形式存儲,每個bucket中放入空的HashMap;

      2、 然后,設置清理線程,處理流程為:

        a)   休眠expirationMillis / (numBuckets-1)毫秒時間(即:expirationSecs / (numBuckets-1)秒);

        b)   對_lock對象上鎖,然后從buckets鏈表中移除最后一個元素;

        c)   向buckets鏈表頭部新加入一個空的HashMap桶,解除_lock對象鎖;

        d)   如果設置了callback函數,則進行回調。

          public TimeCacheMap(int expirationSecs, int numBuckets, ExpiredCallback<K, V> callback) {
              if(numBuckets<2) {
                  throw new IllegalArgumentException("numBuckets must be >= 2");
              }
              _buckets = new LinkedList<HashMap<K, V>>();
              for(int i=0; i<numBuckets; i++) {
                  _buckets.add(new HashMap<K, V>());
              }
      
      
              _callback = callback;
              final long expirationMillis = expirationSecs * 1000L;
              final long sleepTime = expirationMillis / (numBuckets-1);
              _cleaner = new Thread(new Runnable() {
                  public void run() {
                      try {
                          while(true) {
                              Map<K, V> dead = null;
                              Time.sleep(sleepTime);
                              synchronized(_lock) {
                                  dead = _buckets.removeLast();
                                  _buckets.addFirst(new HashMap<K, V>());
                              }
                              if(_callback!=null) {
                                  for(Entry<K, V> entry: dead.entrySet()) {
                                      _callback.expire(entry.getKey(), entry.getValue());
                                  }
                              }
                          }
                      } catch (InterruptedException ex) {
      
                      }
                  }
              });
              _cleaner.setDaemon(true);
              _cleaner.start();
          }

      構造函數需要傳遞三個參數:expirationSecs:超時的時間,單位為秒;numBuckets:桶的個數;callback:超時回調函數。

      為了方便使用,還提供了以下三種形式的構造函數,使用時可以根據需要選擇:

          //this default ensures things expire at most 50% past the expiration time
          private static final int DEFAULT_NUM_BUCKETS = 3;
          public TimeCacheMap(int expirationSecs, ExpiredCallback<K, V> callback) {
              this(expirationSecs, DEFAULT_NUM_BUCKETS, callback);
          }
          public TimeCacheMap(int expirationSecs, int numBuckets) {
              this(expirationSecs, numBuckets, null);
          }
          public TimeCacheMap(int expirationSecs) {
              this(expirationSecs, DEFAULT_NUM_BUCKETS);
          }

      2. 性能分析

      get操作:遍歷各個bucket,如果存在指定的key則返回,時間復雜度為O(numBuckets)

          public V get(K key) {
              synchronized(_lock) {
                  for(HashMap<K, V> bucket: _buckets) {
                      if(bucket.containsKey(key)) {
                          return bucket.get(key);
                      }
                  }
                  return null;
              }
          }

      put操作:將key,value放到_buckets的第一個桶中,然后遍歷其他numBuckets-1個桶,從HashMap中移除其中鍵為key的記錄,時間復雜度為O(numBuckets)

          public void put(K key, V value) {
              synchronized(_lock) {
                  Iterator<HashMap<K, V>> it = _buckets.iterator();
                  HashMap<K, V> bucket = it.next();
                  bucket.put(key, value);
                  while(it.hasNext()) {
                      bucket = it.next();
                      bucket.remove(key);
                  }
              }
          }

      remove操作:遍歷各個bucket,如果存在以key為鍵的記錄,直接刪除,時間復雜度為O(numBuckets)

          public Object remove(K key) {
              synchronized(_lock) {
                  for(HashMap<K, V> bucket: _buckets) {
                      if(bucket.containsKey(key)) {
                          return bucket.remove(key);
                      }
                  }
                  return null;
              }
          }

      containsKey操作:遍歷各個bucket,如果存在指定的key則返回true,否則返回false,時間復雜度為O(numBuckets)

          public boolean containsKey(K key) {
              synchronized(_lock) {
                  for(HashMap<K, V> bucket: _buckets) {
                      if(bucket.containsKey(key)) {
                          return true;
                      }
                  }
                  return false;
              }
          }

      size操作:遍歷各個bucket,累加各個bucket的HashMap的大小,時間復雜度為O (numBuckets)

          public int size() {
              synchronized(_lock) {
                  int size = 0;
                  for(HashMap<K, V> bucket: _buckets) {
                      size+=bucket.size();
                  }
                  return size;
              }
          }

      3. 超時時間

      經過上面對put操作和_cleaner線程的分析,我們已經知道:

        a) put操作將數據放到_buckets的第一個桶中,然后遍歷其他numBuckets-1個桶,從HashMap中移除其中鍵為key的記錄;

        b) _cleaner線程每隔expirationSecs / (numBuckets-1)秒會把_buckets中最后一個桶中的數據從TimeCacheMap中移除掉。

      因此,假設_cleaner線程剛剛清理數據,put函數調用發生將key放入桶中,那么一條數據的超時時間為:

      expirationSecs / (numBuckets-1) * numBuckets = expirationSecs * (1 + 1 / (numBuckets-1))

      然而,假設put函數調用剛剛執行結束,_cleaner線程就開始清理數據,那么一條數據的超時時間為:

      expirationSecs / (numBuckets-1) * numBuckets - expirationSecs / (numBuckets-1) = expirationSecs

      4. 總結

      1、 TimeCacheMap的高效之處在于鎖的粒度小,O(1)時間內完成鎖操作,因此,大部分時間內都可以進行get和put操作。

      2、 get,put,remove,containsKey和size操作都可以在O(numBuckets)時間內完成,其中numBuckets是桶的個數,默認為3。

      3、 未更新數據的超時時間在expirationSecs和expirationSecs * (1 + 1 / (numBuckets-1))之間。

      posted on 2012-06-26 12:32  大圓那些事  閱讀(8812)  評論(2)    收藏  舉報

      導航

      主站蜘蛛池模板: 国产精品1区2区3区在线观看| 国产成人精品亚洲精品密奴| 欧美熟妇性XXXX欧美熟人多毛| 国产三级a三级三级| 男女啪啪高潮激烈免费版| 亚洲国产精品午夜福利| 久在线精品视频线观看| 乱熟女高潮一区二区在线| 国内精品久久毛片一区二区| 德兴市| 女人18片毛片60分钟| 国产伦子沙发午休系列资源曝光 | 免费现黄频在线观看国产| 精品尤物TV福利院在线网站| 成年女人喷潮免费视频| 亚洲成在人线在线播放无码| 一区二区在线观看 激情| 国产一区二区三区不卡观| 久久精品国产99久久6| 国产精品免费中文字幕| 国产高颜值不卡一区二区| 精品人妻中文字幕在线| 熟女少妇精品一区二区| 国产微拍一区二区三区四区| 果冻传媒一区二区天美传媒| 亚洲国产日韩伦中文字幕| 四虎永久精品在线视频| 高潮精品熟妇一区二区三区| 色窝窝免费播放视频在线| h无码精品动漫在线观看| 精品91在线| 国产精品亚洲综合网一区| 99在线精品视频观看免费| 欧美videos粗暴| 国产精品性色一区二区三区| 丝袜国产一区av在线观看| 亚洲欧美人成网站在线观看看 | 国产第一页浮力影院入口| 国产仑乱无码内谢| 亚洲熟妇自偷自拍另欧美| 男女猛烈无遮挡免费视频APP|