ExpireableCache.java
上传用户:huihesys
上传日期:2007-01-04
资源大小:3877k
文件大小:5k
源码类别:

WEB邮件程序

开发平台:

C/C++

  1. /* CVS ID: $Id: ExpireableCache.java,v 1.2 2000/04/06 08:02:02 wastl Exp $ */
  2. package net.wastl.webmail.misc;
  3. import java.util.*;
  4. /*
  5.  * ExpireableCache.java
  6.  *
  7.  * Created: Fri Sep 17 09:43:10 1999
  8.  *
  9.  * Copyright (C) 2000 Sebastian Schaffert
  10.  * 
  11.  * This program is free software; you can redistribute it and/or
  12.  * modify it under the terms of the GNU General Public License
  13.  * as published by the Free Software Foundation; either version 2
  14.  * of the License, or (at your option) any later version.
  15.  * 
  16.  * This program is distributed in the hope that it will be useful,
  17.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19.  * GNU General Public License for more details.
  20.  * 
  21.  * You should have received a copy of the GNU General Public License
  22.  * along with this program; if not, write to the Free Software
  23.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  24.  */
  25. /**
  26.  * This class represents a cache that automatically expires objects when a certain fillness
  27.  * factor is reached.
  28.  *
  29.  * @author Sebastian Schaffert
  30.  * @version
  31.  */
  32. public class ExpireableCache extends Thread {
  33.     
  34.     protected Hashtable cache;
  35.     protected MyHeap timestamps;
  36.     protected int capacity;
  37.     protected float expire_factor;
  38.     protected int hits=0;
  39.     protected int misses=0;
  40.     protected boolean shutdown=false;
  41.     public ExpireableCache(int capacity, float expire_factor) {
  42. super("ExpireableCache");
  43. setPriority(MIN_PRIORITY);
  44. cache=new Hashtable(capacity);
  45. timestamps=new MyHeap(capacity);
  46. this.capacity=capacity;
  47. this.expire_factor=expire_factor;
  48.     }
  49.     public ExpireableCache(int capacity) {
  50. this(capacity,(float).90);
  51.     }
  52.     
  53.     /*
  54.      * Insert an element into the cache
  55.      */
  56.     public synchronized void put(Object key, Object value) {
  57. /* When the absolute capacity is exceeded, we must clean up */
  58. if(cache.size()+1 >= capacity) {
  59.     expireOver();
  60. }
  61. long l=System.currentTimeMillis();
  62. cache.put(key,value);
  63. timestamps.remove(key);
  64. timestamps.insert(key,l);
  65. expireOver();
  66.     }
  67.     public Object get(Object key) {
  68. long l=System.currentTimeMillis();
  69. timestamps.remove(key);
  70. timestamps.insert(key,l);
  71. return cache.get(key);
  72.     }
  73.     public synchronized void remove(Object key) {
  74. cache.remove(key);
  75. timestamps.remove(key);
  76. notifyAll();
  77.     }
  78.     protected synchronized void expireOver() {
  79. while(cache.size()>=(capacity*expire_factor)) {
  80.     String nk=(String)timestamps.next();
  81.     cache.remove(nk);
  82. }
  83.     }
  84.     public void setCapacity(int size) {
  85. capacity=size;
  86.     }
  87.     public int getCapacity() {
  88. return capacity;
  89.     }
  90.     public int getUsage() {
  91. return cache.size();
  92.     }
  93.     public int getHits() {
  94. return hits;
  95.     }
  96.     public int getMisses() {
  97. return misses;
  98.     }
  99.     public void hit() {
  100. hits++;
  101.     }
  102.     public void miss() {
  103. misses++;
  104.     }
  105.     public void shutdown() {
  106. shutdown=true;
  107.     }
  108.     public void run() {
  109. while(!shutdown) {
  110.     try {
  111. wait(10000);
  112.     } catch(InterruptedException e) {}
  113.     expireOver();
  114. }
  115.     }
  116.     /**
  117.      * Implement a simple heap that just returns the smallest long variable/Object key pair.
  118.      */
  119.     protected class MyHeap {
  120. int num_entries;
  121. long[] values;
  122. Object[] keys;
  123. MyHeap(int capacity) {
  124.     values=new long[capacity+1];
  125.     keys=new Object[capacity+1];
  126.     num_entries=0;
  127. }
  128. /**
  129.  * Insert a key/value pair
  130.  * Reorganize Heap afterwards
  131.  */
  132. public void insert(Object key, long value) {
  133.     keys[num_entries]=key;
  134.     values[num_entries]=value;
  135.     num_entries++;
  136.     increase(num_entries);
  137. }
  138. /**
  139.  * Return and delete the key with the lowest long value. Reorganize Heap.
  140.  */
  141. public Object next() {
  142.     Object ret=keys[0];
  143.     keys[0]=keys[num_entries-1];
  144.     values[0]=values[num_entries-1];
  145.     num_entries--;
  146.     decrease(1);
  147.     
  148.     return ret;
  149. }
  150. /**
  151.  * Remove an Object from the Heap.
  152.  * Unfortunately not (yet) of very good complexity since we are doing 
  153.  * a simple linear search here.
  154.  * @param key The key to remove from the heap
  155.  */
  156. public void remove(Object key) {
  157.     for(int i=0;i<num_entries;i++) {
  158. if(key.equals(keys[i])) {
  159.     num_entries--;
  160.     int cur_pos=i+1;
  161.     keys[i]=keys[num_entries];
  162.     decrease(cur_pos);
  163.     break;
  164. }
  165.     }
  166. }
  167. /**
  168.  * Lift an element in the heap structure
  169.  * Note that the cur_pos is actually one larger than the position in the array!
  170.  */
  171. protected void increase(int cur_pos) {
  172.     while(cur_pos > 1 && values[cur_pos-1] < values[cur_pos/2-1]) {
  173. Object tmp1=keys[cur_pos/2-1];keys[cur_pos/2-1]=keys[cur_pos-1];keys[cur_pos-1]=tmp1;
  174. long tmp2=values[cur_pos/2-1];values[cur_pos/2-1]=values[cur_pos-1];values[cur_pos-1]=tmp2;
  175. cur_pos /= 2;
  176.     }
  177. }     
  178. /**
  179.  * Lower an element in the heap structure
  180.  * Note that the cur_pos is actually one larger than the position in the array!
  181.  */
  182. protected void decrease(int cur_pos) {
  183.     while((cur_pos*2 <= num_entries && values[cur_pos-1] > values[cur_pos*2-1]) ||
  184.   (cur_pos*2+1 <=num_entries && values[cur_pos-1] > values[cur_pos*2])) {
  185. int lesser_son;
  186. if(cur_pos*2+1 <= num_entries) {
  187.     lesser_son=values[cur_pos*2-1]<values[cur_pos*2]?cur_pos*2:cur_pos*2+1;
  188. } else {
  189.     lesser_son=cur_pos*2;
  190. }
  191. Object tmp1=keys[cur_pos-1];keys[cur_pos-1]=keys[lesser_son-1];keys[lesser_son-1]=tmp1;
  192. long tmp2=values[cur_pos-1];values[cur_pos-1]=values[lesser_son-1];values[lesser_son-1]=tmp2;
  193. cur_pos=lesser_son;
  194.     }
  195. }     
  196.     }
  197. } // ExpireableCache