Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Java программирование > Общие вопросы по Java, Java SE, Kotlin
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 04.12.2016, 16:25   #1
Evdar
Пользователь
 
Регистрация: 07.12.2015
Сообщений: 19
По умолчанию Создание кеш с определенным временем хранения объектов

Здравствуйте, есть задача, сделать кэш, с методами добавить(ключ, объект, время жизни, единицы времени жизни), получить(по ключу) и метод удалить(по ключу). Вот все на что я способен...не понимаю как сделать так что бы по истечению времени жизни объекта, он удалялся, да и не знаю куда единицы времени жизни впихнуть...помогите пожалуйста тугодуму...

Код:
public class Kesh {
 
    private ConcurrentHashMap<Integer, Obj> map = new ConcurrentHashMap<Integer, Obj>();
 
    public void add(int key, Object obj, int timeAlive) throws InterruptedException {
        map.put(key, new Obj(timeAlive));
    }
 
    public Obj get(int key) {
        for (Map.Entry<Integer, Obj> pair : map.entrySet()) {
            if (pair.getKey() == key) {
                return pair.getValue();
            }
        }
        return null;
    }
 
    public int getSize() {
        return map.size();
    }
 
    public void remove(int key) {
        Iterator<Map.Entry<Integer, Obj>> it = map.entrySet().iterator();
        while (it.hasNext()) {
            int currentKey = it.next().getKey();
            if (currentKey == key) {
                map.remove(currentKey);
            }
        }
    }
 
    @Override
    public String toString() {
        return "Kesh{" +
                "map=" + map +
                '}';
    }
 
    static class Obj {
        private final long timeLife;
 
        private Obj(int timeLife) throws InterruptedException {
            this.timeLife = System.currentTimeMillis() + timeLife;
        }
 
        public boolean isAlive(long currentTimeMillis) {
            return currentTimeMillis < timeLife;
        }
    }
}
Evdar вне форума Ответить с цитированием
Старый 05.12.2016, 17:09   #2
New man
Форумчанин
 
Регистрация: 24.01.2011
Сообщений: 774
По умолчанию

По-моему, это неправильно.
Цитата:
Код:
public void remove(int key) {
        Iterator<Map.Entry<Integer, Obj>> it = map.entrySet().iterator();
        while (it.hasNext()) {
            int currentKey = it.next().getKey();
            if (currentKey == key) {
                map.remove(currentKey);
            }
        }
    }
Надо так:
Код:
public void remove(int key) {
        map.remove(key);        
    }

public Obj get(int key) {
        return map.get(key);
    }
Это намного быстрее будет работать. Вообще, делать перебор по Map, ища соответствие ключу, довольно говнокодисто.



Если у тебя время в тиках, то можно сделать так:
Код:
private Map<Integer, Set<Integer>> timeKeys = new ConcurentHashMap<>();

....

// Вызывается в каждый тик
public onTick(int tickCount){
   Set<Integer> removeKeys = timeKeys.get(tickCount);
   for(int key:removeKeys){
       remove(key);
   }
   timeKeys.remove(tickCount);
}

//При добавлении элемента:
public add(int key, obj item, int lifeTime){
     int endTime = getCurrentTickCount()+lifeTime;
     if (! timeKeys.containsKey(endTime)){
          timeKeys.put(endTime, new ConcurrentSkipListSet<Integer>());
     }
     Set<Integer> timeSet = timeKeys.get(endTime);
     if (timeSet!=null)
        timeSet.add(key);

     // Далее твой старый код.
     ....
}
a.k.a. Angelicos Phosphoros
Мой сайт
New man вне форума Ответить с цитированием
Старый 07.12.2016, 22:48   #3
Evdar
Пользователь
 
Регистрация: 07.12.2015
Сообщений: 19
По умолчанию

Согласен это очень говнокодисто....)
Спасибо вам за ответ) уже разобрался)
вот если интересно
Код:
public class SimpleCacheImpl<K, V> implements Cache<K, V> {
    private final Map<K, Item <V>> map = new HashMap<>();

    public SimpleCacheImpl() {
        super();
        Thread th = new Thread(new ClearRunnable(), "Clear-Thread");
        th.setDaemon(true);
        th.setPriority(Thread.MIN_PRIORITY);
        th.start();
    }

    @Override
    public void put(K key, V value, int ttl, TimeUnit timeUnit) {
        long expireTime = System.currentTimeMillis() + timeUnit.toMillis(ttl);
        synchronized (map) {
            map.put(key, new Item<V>(value, expireTime));
        }
    }

    @Override
    public V get(K key) {
        Item<V> item = null;
        synchronized (map) {
            item = map.get(key);
        }
        if(item == null || !item.isValid()) {
            return null;
        } else {
            return item.value;
        }
    }

    @Override
    public void remove(K key) {
        synchronized (map) {
            map.remove(key);
        }

    }

    private class ClearRunnable implements Runnable {

        @Override
        public void run() {
            while(!Thread.interrupted()){
                try {
                    Set<K> keys = map.keySet();
                    for(K key : keys) {
                        synchronized (map) {
                            Item<V> item = map.get(key);
                            if(!item.isValid()) {
                                map.remove(key);
                            }
                        }
                        if(Thread.interrupted()) {
                            return;
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }

                try {
                    TimeUnit.SECONDS.sleep(10);
                } catch (InterruptedException e) {
                    return;
                }
            }

        }

    }

    private static class Item<V> {
        private final V value;
        private final long expireTime;
        Item(V value, long expireTime) {
            super();
            this.value = value;
            this.expireTime = expireTime;
        }
        private boolean isValid(){
            return System.currentTimeMillis() <= expireTime;
        }
    }
}

Последний раз редактировалось Evdar; 08.12.2016 в 17:37.
Evdar вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Программа камера хранения, работа с временем не могу разобраться помогите) farefo Общие вопросы Delphi 4 21.11.2015 20:40
Создание и уничтожение объектов. Время жизни объектов C++/C# Anett// Помощь студентам 0 24.10.2011 23:26
Создание объектов voltageminh Общие вопросы C/C++ 7 11.05.2011 08:51
Создание листа с определенным именем. bud-dy Microsoft Office Excel 10 28.01.2011 13:57
Создание объектов с хендлом VintProg Gamedev - cоздание игр: Unity, OpenGL, DirectX 30 31.07.2009 13:36