All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.rythmengine.cache.SimpleCacheService Maven / Gradle / Ivy

Go to download

A strong typed high performance Java Template engine with .Net Razor like syntax

There is a newer version: 1.4.2
Show newest version
/* 
 * Copyright (C) 2013 The Rythm Engine project
 * Gelin Luo 
 *
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
*/
package org.rythmengine.cache;

import org.rythmengine.extension.ICacheService;
import org.rythmengine.internal.RythmThreadFactory;
import org.rythmengine.logger.ILogger;
import org.rythmengine.logger.Logger;

import java.io.Serializable;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * A simple cache service implementation
 */
public class SimpleCacheService implements ICacheService {

    private static final ILogger logger = Logger.get(SimpleCacheService.class);

    public static final SimpleCacheService INSTANCE = new SimpleCacheService();

    private static class TimerThreadFactory extends RythmThreadFactory {
        private TimerThreadFactory() {
            super("rythm-timer");
        }
    }

    private ScheduledExecutorService scheduler = null;

    private SimpleCacheService() {
        startup();
    }

    private static class Item implements Comparable {
        String key;
        Serializable value;
        long ts;
        int ttl;

        Item(String key, Serializable value, int ttl) {
            this.key = key;
            this.value = value;
            this.ttl = ttl;
            this.ts = System.currentTimeMillis();
        }
        
        @Override
        public int compareTo(Item that) {
            return ttl - that.ttl;
        }
    }

    private ConcurrentHashMap cache_ = new ConcurrentHashMap();
    private Queue items_ = new PriorityQueue();

    @Override
    public void put(String key, Serializable value, int ttl) {
        if (null == key) throw new NullPointerException();
        if (0 >= ttl) {
            ttl = defaultTTL;
        }
        Item item = cache_.get(key);
        if (null == item) {
            Item newItem = new Item(key, value, ttl);
            item = cache_.putIfAbsent(key, newItem);
            if (null != item) {
                item.value = value;
                item.ttl = ttl;
            } else {
                items_.offer(newItem);
            }
        } else {
            item.value = value;
            item.ttl = ttl;
        }
    }

    @Override
    public void put(String key, Serializable value) {
        put(key, value, defaultTTL);
    }

    @Override
    public Serializable remove(String key) {
        Item item = cache_.remove(key);
        return null == item ? null : item.value;
    }

    @Override
    public void evict(String key) {
        cache_.remove(key);
    }

    @Override
    public void clear() {
        cache_.clear();
        items_.clear();
    }
    
    @Override
    public Serializable get(String key) {
        Item item = cache_.get(key);
        return null == item ? null : item.value;
    }

    @Override
    public boolean contains(String key) {
        return cache_.contains(key);
    }

    private int defaultTTL = 60;

    @Override
    public void setDefaultTTL(int ttl) {
        if (ttl == 0) throw new IllegalArgumentException("time to live value couldn't be zero");
        this.defaultTTL = ttl;
    }

    @Override
    public void shutdown() {
        clear();
        if (null != scheduler) {
            scheduler.shutdown();
            scheduler = null;
        }
    }
    
    @Override
    public void startup() {
        if (null == scheduler) {
            scheduler = new ScheduledThreadPoolExecutor(1, new TimerThreadFactory());
            scheduler.scheduleAtFixedRate(new Runnable() {
                @Override
                public void run() {
                    if (items_.size() == 0) {
                        return;
                    }
                    long now = System.currentTimeMillis();
                    if (logger.isTraceEnabled()) {
                        logger.trace(">>>>now:%s", now);
                    }
                    while(true) {
                        Item item = items_.peek();
                        if (null == item) {
                            break;
                        }
                        long ts = item.ts + item.ttl * 1000;
                        if ((ts) < now + 50) {
                            items_.poll();
                            cache_.remove(item.key);
                            if (Logger.isTraceEnabled()) {
                                logger.trace("- %s at %s", item.key, ts);
                            }
                            continue;
                        } else {
                            if (Logger.isTraceEnabled()) {
                                logger.trace(">>>>ts:  %s", ts);
                            }
                        }
                        break;
                    }
                }
            }, 0, 100, TimeUnit.MILLISECONDS);
        }
    }

    @Override
    protected void finalize() throws Throwable {
        shutdown();
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy