How to start a background thread that regularly clears some items in a list?

I am currently using cache. I performed the basic implementation as shown below. What I want to do is to start a thread that will delete a record that satisfies certain conditions.

class Cache { int timeLimit = 10; //how long each entry needs to be kept after accessed(marked) int maxEntries = 10; //maximum number of Entries HashSet<String> set = new HashSet<String>(); public void add(Entry t){ .... } public Entry access(String key){ //mark Entry that it has been used //Since it has been marked, background thread should remove this entry after timeLimit seconds. return set.get(key); } .... } 

My question is: how do I implement a background thread so that the thread bypasses the entries in the set and removes those that were marked && (last access time - now)>timeLimit ?

change

The best simplified version of the codes is that I did not write synchronized statements.

+3
source share
5 answers

Why are you reinventing the wheel? EhCache (and any decent cache implementation) will do this for you. Also much lighter MapMaker Cache from Guava can automatically delete old entries.

If you really want to implement this on your own, in fact it is not so simple.

  • Remember to sync. To store records, use the ConcurrentHashMap or synchronized . It can be very difficult.

  • Somehow you should keep the last access time somehow from each record. Each time you access a record, you must update this timestamp.

  • Think of an eviction policy. If there are more maxEntries in the cache, which ones should be removed first?

  • Do you really need a background thread?

    This is surprising, but EhCache (ready and verified by the enterprise) does not use a background thread to invalidate old entries). Instead, he waits until the card is full and lazily deletes entries. This seems like a good compromise since the flows are expensive.

  • If you have a background thread, should there be one cache or one global? Do you start a new thread when creating a new cache or do you have a global list of all caches? This is harder than you think ...

As soon as you answer all these questions, the implementation will be quite simple: go through all the records every second or so, and if the condition that you have already recorded is fulfilled, delete the record.

+8
source

First, access your collection either synchronized or use ConcurrentHashSet a Set based ConcurrentHashMap , as mentioned in the comments below.

Secondly, write your new thread and implement it as an infinite loop that periodically iterates over the previous collection and removes the elements. You must write this class so that it is initialized with the correct collection in the constructor, so you don’t have to worry about “how do I access the corresponding collection”.

0
source

I would use a Guava Cache type for this, personally. It is already thread safe and has built-in methods for evicting from the cache based on some time limit. If you want the thread to change it periodically, you can simply do something like this:

  new Thread(new Runnable() { public void run() { cache.cleanUp(); try { Thread.sleep(MY_SLEEP_DURATION); } catch (Exception e) {}; } }).start(); 
0
source

I don't think you really need a background thread. Instead, you can simply delete expired entries before or after the search. This simplifies the whole implementation and it is very difficult to distinguish it.

BTW: If you use LinkedHashMap, you can use it as an LRU cache by overriding removeEldestEntry (see javadocs example)

0
source

First of all, your code is incomplete because there is no get(key) on HashSet (so I assume that you are referring to a certain Map ), and your code does not mention “marking”. There are also many ways to do caching, and it's hard to choose the best solution without knowing what you are trying to cache and why.

When implementing a cache, it is usually assumed that multiple threads will access the data structure at the same time. So, the first thing you need to do is use the backup data structure, which is thread safe. HashMap not thread safe, but ConcurrentHashMap is. There are also a number of other parallel implementations of Map , namely in Guava , Javolution, and a high-level library . There are other ways to create caches besides cards, and their usefulness depends on your use case. Despite this, you will most likely need to make the stream data structure redundant, even if you decide that you do not need a background thread, and instead expire the expired objects, trying to extract them from the cache. Or let GC delete entries with SoftReference s.

After you have made the cache internals thread safe, you can simply start a new (most likely demonized) thread that periodically searches / iterates the cache and deletes old entries. The thread will do this in a loop (until it is interrupted if you want to stop it again), and then sleeps for a while after each sweep.

However, you should consider whether you should do this and create your own cache implementation. Writing thread-safe code is not easy, and I recommend that you study it before trying to write your own cache implementation. I can recommend the Java Concurrency book in practice.

An easier way to do this, of course, is to use an existing cache implementation. There are many options available on Java-land, all with their own unique set of tradeoffs.

  • EhCache and JCS are both general purpose caches that suit most of the caching needs found in a typical "enterprise" application.
  • Infinispan is a cache optimized for distributed use, and thus can cache more data than what can fit on a single machine. I also like its ConcurrentMap API.
  • As already mentioned, the Googles Guava library has a Cache API, which is very useful for small caches in memory.

Since you want to limit the number of entries in the cache, you might be interested in the object pool, not the cache.

  • Apache Commons-Pool is widely used and has APIs that resemble what you are trying to create yourself.
  • Stormpot , on the other hand, has a completely different API, and I almost mentioned it just because I wrote it. This is probably not what you want, but who can be sure without knowing what you are trying to cache and why?
0
source

All Articles