package com.atom.util;
import j2ee.core.utils.TextUtils;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.atom.memcache.CacheOperate;
public class AtsHashtable<K, V> extends Hashtable<K, V>{
private String TABLE_FLAG = TextUtils.getUUID();
private Hashtable<K,V> outsideMap;
private static List<Class> SINGLE_OBJECT = new ArrayList<Class>();
static{
SINGLE_OBJECT.add(String.class);
}
{
initOutsideMap();
}
private void initOutsideMap(){
outsideMap = (Hashtable<K,V>)getFromOutSide(TABLE_FLAG);
if(outsideMap==null){
outsideMap = new Hashtable<K,V>();
}
}
public void initOutsideData(String id){
Hashtable<K,V> outsideData = (Hashtable<K,V>)getFromOutSide(id);
if(outsideData!=null){
TABLE_FLAG = id;
outsideMap = outsideData;
}
}
@Override
public synchronized void clear() {
removeFromOutSide(TABLE_FLAG);
super.clear();
}
@Override
public synchronized boolean contains(Object value) {
return super.contains(value) || this.outsideMap.contains(value);
}
@Override
public synchronized boolean containsKey(Object key) {
return super.containsKey(key) || this.outsideMap.containsKey(key);
}
@Override
public boolean containsValue(Object value) {
return super.containsValue(value) || this.outsideMap.containsValue(value);
}
@Override
public synchronized Enumeration elements() {
return getUniteTable().elements();
}
@Override
public Set entrySet() {
return getUniteTable().entrySet();
}
@Override
public synchronized V get(Object key) {
V result = super.get(key);
result = result==null?outsideMap.get(key):result;
return result;
}
@Override
public synchronized boolean isEmpty() {
return super.isEmpty() && outsideMap.isEmpty();
}
@Override
public synchronized Enumeration keys() {
return getUniteTable().keys();
}
@Override
public Set keySet() {
return getUniteTable().keySet();
}
@Override
public synchronized V put(K key, V value) {
if(isOutsideObject(value.getClass())){
Object o = super.get(TABLE_FLAG);
//判断TABLE_FLAG这个key是否放入过自身
if(o==null){
super.put((K)TABLE_FLAG, (V)outsideMap);
}
//old memcached好像会直接拷贝对象数据,所以不能像往常session那样操作
// putToOutSide();
// return outsideMap.put(key, value);
//new 将outsideMap填充新数据后再更新memcached
V rtn = outsideMap.put(key,value);
putToOutSide();
return rtn;
}else{
return super.put(key, value);
}
}
@Override
public synchronized void putAll(Map t) {
super.putAll(t);
}
@Override
public synchronized V remove(Object key) {
if(this.containsKey(key)){
return super.remove(key);
}else{
//这么删好像会出问题,因为memcached上保存的是TABLE_FLAG这个key
//不是要删除的对象的key
//old
// removeFromOutSide(key);
// return outsideMap.remove(key);
//new
V o = outsideMap.remove(key);
//如果没有对象放缓存里了,那么清除缓存
if(outsideMap.size()==0){
removeFromOutSide(TABLE_FLAG);
}else{
//否则把删除后的outsideMap放到缓存
putToOutSide();
}
return o;
}
}
@Override
public Collection values() {
return getUniteTable().values();
}
private void putToOutSide(){
CacheOperate.addByUser(TABLE_FLAG, outsideMap);
}
private Object getFromOutSide(String key){
return CacheOperate.getByUser(key);
}
private void removeFromOutSide(Object key){
CacheOperate.deleteByUser(String.valueOf(key));
}
private Hashtable<K,V> getUniteTable(){
Hashtable<K,V> _ht = new Hashtable<K, V>();
//old 会出现死循环错误
//_ht.putAll(this);
//new 自己手动的模仿putAll放置
Set<Map.Entry<K,V>> entrySet = super.entrySet();
for (Map.Entry<? extends K, ? extends V> e : entrySet)
_ht.put(e.getKey(), e.getValue());
_ht.putAll(outsideMap);
return _ht;
}
private boolean isOutsideObject(Object o){
return !SINGLE_OBJECT.contains(o);
}
public String getTableFlag(){
return this.TABLE_FLAG;
}
}
转载于:https://www.cnblogs.com/qq1988627/archive/2011/07/20/6606931.html