2013-12-10 33 views
1

我正在实现与expiry的高速缓存。我正在使用ScheduledThreadExecutor来安排从缓存中删除条目。我的问题是执行者永远不会关闭。我在shutdownHook中尝试过executor.shutdown()方法,但是即使在我的主程序执行完成后它也没有执行。我也不喜欢终结者。我的代码如下。当主程序退出时,我想要执行closeCache()方法。程序退出时的关机执行程序服务

public class TimeCacheManual<K,V> { 

private final int maxSize; 
private final long timeToLive; 
private Map<K, V> keyValueMap; 
private Map<K,ScheduledFuture > keySchedulerMap; 
private Queue<K> keys; 
private final ScheduledExecutorService scheduler; 
/* 
* creates new instance of TimeBasedEvictionCache. 
* @param maxSize must be greater than zero 
* @param timeToLive must be greater than zero 
* @throws IllegalArgumentException if {@code maxSize<1||timeToLive<1} 
* */ 
public TimeCacheManual(int maxSize,long timeToLive) { 
    if(maxSize<1||timeToLive<1){ 
     throw new IllegalArgumentException(); 
    } 
    this.maxSize = maxSize; 
    this.timeToLive = timeToLive; 
    keyValueMap = new ConcurrentHashMap<K, V>(maxSize); 
    keySchedulerMap = new ConcurrentHashMap<K, ScheduledFuture>(maxSize); 
    keys = new ConcurrentLinkedQueue<K>(); 
    scheduler = Executors.newScheduledThreadPool(maxSize); 

} 
/* 
* adds a key value pair to the cache. 
* @param key 
* @param value associated with key 
*/ 
public synchronized void put(K key,V value) { 
    if (keyValueMap.containsKey(key)) { 
     refreshKey(key); 
    } 
    else{ 
     keys.add(key); 
    } 
    keyValueMap.put(key, value); 
    scheduleEviction(key); // schedules eviction of the key after timeToLive 
} 
/* 
* schedules eviction of particular key after timeToLive 
* @param key 
*/ 
private void scheduleEviction(final K key){ 
ScheduledFuture sf= scheduler.schedule(new Runnable(){ 
     @Override public void run(){ 
      keys.remove(key); 
      keyValueMap.remove(key); 
     } 
    }, 
      timeToLive, 
      TimeUnit.MILLISECONDS); 
    keySchedulerMap.put(key,sf); 

} 
/* 
* used to get a value associated with a given key. returns null if no value is associated with given key 
* @param key 
* @return value associated with key, null if no value is associated with particular key 
*/ 
public synchronized V get(K key) { 
    refreshKey(key); 
    scheduleEviction(key); 
    return keyValueMap.get(key); 
} 
/* 
* updates the order of keys according to a particular policy 
* @param key to be refreshed 
*/ 
private void refreshKey(K key){ // refreshing the order of keys 
    keySchedulerMap.get(key).cancel(true) ; 
    keys.remove(key);   //LRU policy 
    keys.add(key); 
} 
public void closeCache(){ 
    scheduler.shutdownNow() ; 
} 

}

回答

1

感谢您的回复。我正在创建一个图书馆。所以它不会知道何时调用executor.shutdown(),除非库的用户明确调用shutdown()。无论如何,我得到的解决方案。我让执行器成为守护进程线程,以便在主程序退出时自动终止。代码来制作一个守护进程执行器在下面给出

scheduler = Executors.newScheduledThreadPool(maxSize,new ThreadFactory() { 
     @Override 
     public Thread newThread(Runnable r) { 
      Thread t = new Thread(r); 
      t.setDaemon(true); 
      return t; 
     } 
    }); 

谢谢你们。希望这会帮助别人

0

executor.shutdown()关闭线程池已提交的任务完成后才会全部。看起来你有计时器计划的任务让执行器运行。取消它们,或致电shutdownNow

相关问题