How to fire off a asynch thread in a web application, and guarantee only 1 thread fires?
I want to cache a object in memory. Regenerating the object when the cache expires is fairly expensive, 开发者_如何学Goso I want to do the following:
When the cache is "about" to expire, I want to fire off a asynchronous thread that will go and rebuild the object and then reset the cache.
One thing I am worry about is multiple threads firing to fetch the object to cache, I only want a single thread doing this, realizing many people will be hitting the website.
This might not be the best use case to do this, but I want to know how to do this sort of thing.
You're looking for java.util.concurrent.Executors.newSingleThreadScheduledExecutor():
Creates a single-threaded executor that can schedule commands to run after a given delay, or to execute periodically. (Note however that if this single thread terminates due to a failure during execution prior to shutdown, a new one will take its place if needed to execute subsequent tasks.) Tasks are guaranteed to execute sequentially, and no more than one task will be active at any given time. Unlike the otherwise equivalent newScheduledThreadPool(1) the returned executor is guaranteed not to be reconfigurable to use additional threads.
You should use a ScheduledExecutorService. If I were to write this, I would do it in a similar way to:
Object cachedObject = null;
ReadWriteLock lock = new ReentrantReadWriteLock();
ScheduledExecutorService cacheService = Executors.newScheduledThreadPool(1);
cacheService.scheduleAtFixedRate(new Runnable(){
public void run(){
lock.writeLock().lock();
try{
cachedObjcet = //built object
}finally{
lock.writeLock().unlock();
}
}
}, 0, N, X);
//where
// N is the amount of time until expiriation
// X is the time units that N is represented by
public Object getCachedObject(){
lock.readLock().lock();
try{
return cachedObject;
}finally{
lock.readLock().unlock();
}
}
I'd personally use a scheduler of some sort to trigger the re-creation of the object and the cache renewal and set the object to never be invalidated automatically in the cache.
You could start a thread during initialization of your web application and let him wait for expiration of your expensive object, go sleep again and wait for next expiration, ...
you should be able to use lock(this){}
on a section of code to ensure that only one thread can access it at a time.
alternatively, you can cache a boolean value and set it to true when you fire your async thread, checking it before firing said thread and if its false, abort the intended operation
精彩评论