Reputation: 3587
I have seen question How do determine if an object is locked (synchronized) so not to block in Java?
But I have problem on which I can not figure out solution.
In my web application is process in which refresh of data container and that can take long time. Refresh is forced to be made in time intervals. Of course when one refresh is still on container working another cannot (to do not corrupt data in container).
I want to use background thread to refresh container. Multiple background workers can be working at the same time on multiple containers (different workers for different user sessions, every user session can have different data in their container).
Of course I can do synchronize(myContainer)
in worker to force that any other worker is not currently updating this particular container. But I rather want to check if any worker is working on container and exit, if is. Also I would like to not change code of container, so I would like not to add ReentrantLock inside container class and lock on that.
So worker have MyContainer
instance and want to determine if any other worker is currently refreshing this container instance.
Any ideas how to achieve that?
Upvotes: 1
Views: 392
Reputation: 18158
I would put the containers in a ConcurrentLinkedQueue and have the worker threads poll
the queue i.e.
Container container;
while((container = queue.poll()) != null) {
container.refresh();
}
Then you have two options depending on whether the containers are tracking when they are being refreshed.
offer
the refreshed containers back into the queue as soon as they're refreshed. You can use an if(container.refreshTime < X)
guard to ensure that you don't refresh the container twice in the same time interval.ConcurrentLinkedQueues
and alternate between them: poll
on queue1
and offer
the refreshed container on queue2
, and when queue1
is empty sleep until the next time interval, at which point poll
on queue2
and offer
the refreshed containers on queue1
. offer
the containers back into the queue when the worker threads have finished refreshing all of the containers and have gone to sleep.Upvotes: 1
Reputation: 1474
use an AtomicBoolean
, put this code in your MyContainer
class:
AtomicBoolean isRefreshing = new AtomicBoolean(false);
void refresh() {
if ( isRefreshing.compareAndSet( false, true)) {
try {
// refresh
} finally {
isRefreshing.set( false);
}
}
}
If you can not touch MyContainer, maybe create a RefreshWrapper holding the AtomicBoolean and the MyContainer instance.
Upvotes: 2
Reputation: 21778
If you need to pre-check if the object has not already been locked by some other thread, this should be possible with Thread.holdsLock method.
If this is not enough, look into the advanced lock classes. These locks provide the rich set of features (check that is waiting on the lock, try to lock with time out, lock interruptably, etc). They should provide enough features to solve your problem.
Upvotes: 0