FixedTTLCache实现

来源:互联网 发布:c语言也能干大事 网盘 编辑:程序博客网 时间:2024/06/06 15:47

所有item的TTL都一样,比如所有的http session的过期时间默认30分钟,idle超过30分钟就失效。相对的是每个item指定TTL的缓存。

实现和LRU类似,都是map + list,不同的是触发机制不是容量满,而是idle时间。专门一个线程check,重点是,不是O(n)的遍历检查,而是利用队列维护先后顺序,队头是最老的,如果队头都没过期,其他的都不可能过期,而且check线程会wait这个时间差再次check,而不是以固定的间隔无谓的check

class DeList<T> {public static class Node<T> {public T data;public Node<T> prev;public Node<T> next;public Node(T data) {this.data = data;}public Node(T data, Node<T> prev, Node<T> next) {this.data = data;this.prev = prev;this.next = next;}}Node<T> head = null, tail = null;public void addLast(Node<T> node) {node.prev = null;node.next = null;if (tail == null) {head = node;} else {tail.next = node;node.prev = tail;}tail = node;}public void remove(Node<T> node) {if (node.prev != null) node.prev.next = node.next;if (node.next != null) node.next.prev = node.prev;if (node == head) head = node.next;if (node == tail) tail = node.prev;}public T peekFirst() {return head == null ? null : head.data;}public T pollFirst() {if (head == null) return null;Node<T> node = head;head = head.next;if (head != null) head.prev = null;else tail = null;return node.data;}}public class FixedTTLCache<K, V> implements Iterable<FixedTTLCache<K, V>.Entry>{public class Entry{K key;V value;long dueTime; //millisecond from 1970public Entry(K key, V value, long dueTime) {this.key = key;this.value = value;this.dueTime = dueTime;}}private Map<K, DeList.Node<Entry>> locator = new HashMap<K, DeList.Node<Entry>>();private DeList<Entry> list = new DeList<Entry>();private long TTL;private Lock lock = new ReentrantLock();private Condition available = lock.newCondition();private Thread expireThread;private volatile boolean exit = false;public FixedTTLCache(long ttl) {this.TTL = ttl;expireThread = new Thread(new Runnable() {public void run() {expireCheck();}});expireThread.start();}public void put(K key, V value) {try {lock.lock();DeList.Node<Entry> node = locator.get(key);if (node != null) {node.data.value = value;list.remove(node);} else {node = new DeList.Node<Entry>(new Entry(key, value, -1));locator.put(key, node);}list.addLast(node);node.data.dueTime = System.currentTimeMillis() + TTL;if (locator.size() == 1) this.available.signalAll();} finally {lock.unlock();}}public V get(K key) {try {lock.lock();DeList.Node<Entry> node = locator.get(key);if (node == null) return null;list.remove(node);list.addLast(node);node.data.dueTime = System.currentTimeMillis() + TTL;return node.data.value;}finally {lock.unlock();}}public int size() {return this.locator.size();}@Overridepublic Iterator<Entry> iterator() {return new Iterator<Entry>() {DeList.Node<Entry> cur = list.head;@Overridepublic boolean hasNext() {return cur != null;}@Overridepublic Entry next() {Entry ret = cur.data;cur = cur.next;return ret;}};}private void expireCheck() {while (!exit) {try {lock.lock();Entry e = list.peekFirst();if (e == null) {System.out.println("Checker: empty, waitting...");available.await();}else {if (e.dueTime > System.currentTimeMillis()) {available.await(e.dueTime - System.currentTimeMillis(), TimeUnit.MILLISECONDS);} else {e = list.pollFirst();System.out.println("expire key " + e.key);locator.remove(e.key);}}} catch (InterruptedException e) {} finally {lock.unlock();}}System.out.println("Checker exits.");}public void stop() {this.exit = true;try {lock.lock();available.signalAll();} finally {lock.unlock();}}}





0 0
原创粉丝点击