Java 程序退出时关闭执行器服务

Java 程序退出时关闭执行器服务,java,executorservice,Java,Executorservice,我正在实现一个过期的缓存。我使用ScheduledThreadExecutor来计划从缓存中删除条目。我的问题是执行人永远不会被关闭。我在shutdownHook中尝试了executor.shutdown()方法,但即使在我的主程序完成执行之后,它也不会被执行。我也不喜欢终结器。我的代码如下。我希望主程序退出时执行closeCache()方法 public class TimeCacheManual<K,V> { private final int maxSize; private

我正在实现一个过期的缓存。我使用
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() ;
}
公共类时间缓存手册{
私有最终整数最大值;
私人最终长期生活;
私有地图keyValueMap;
私有映射密钥调度映射;
专用队列密钥;
专用最终调度器ExecutorService调度器;
/*
*创建TimeBaseDeviceCache的新实例。
*@param maxSize必须大于零
*@param timeToLive必须大于零

*如果{@code maxSize
executor.shutdown()
仅在所有已提交的任务完成后关闭线程池,则@throws IllegalArgumentException将引发IllegalArgumentException。看起来您有使executor运行的计时器计划任务。取消它们,或调用。

executor.shutdown()
只有在所有已提交的任务完成后才关闭线程池。看起来您有计时器计划的任务,可以让executor运行。取消它们,或者调用。

感谢您的回复。我正在创建一个库。因此它不知道何时调用
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;
        }
    });

谢谢你们。希望这能帮助别人。谢谢你们的回复。我正在创建一个库。所以它不知道什么时候调用
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;
        }
    });
谢谢你们,希望这能帮助别人