Synchronizing on cached items - java

I'm using something like
Cache<Integer, Item> cache;
where the Items are independent of each other and look like
private static class Item {
private final int id;
... some mutable data
synchronized doSomething() {...}
synchronized doSomethingElse() {...}
}
The idea is to obtain the item from the cache and call a synchronized method on it. In case of a miss, the item can be recreated, that's fine.
A problem occurs when an item gets evicted from the cache and recreated while a thread runs a synchronized method. A new thread obtains a new item and synchronizes on it... so for a single id, there are two threads inside the synchronized method. FAIL.
Is there an easy way around it? It's Guava Cache, if it helps.

I think the suggestion from Louis, using the the keys for locking is the most simple and practical one. Here is code some snippet, that, without the help of Guava libraries, illustrates the idea:
static locks[] = new Lock[ ... ];
static { /* initialize lock array */ }
int id;
void doSomething() {
final lock = locks[id % locks.length];
lock.lock();
try {
/* protected code */
} finally {
lock.unlock();
}
}
The size of the lock array limits the maximum amount of parallelism you get. If your code is only using CPU, you can initialize it by the number of available processors and this is the perfect solution. If your code waits for I/O you might need an arbitrary big array of locks or you limit the number of threads that can run the critical section. In this case another approach might be better.
Comments on a more conceptual level:
If you want to prevent the item from being evicted, you need a mechanism called pinning. Internally this is used by most cache implementations, e.g. for blocking during I/O operations. Some caches may expose a way to do it by the applications.
In a JCache compatible cache, there is the concept of an EntryProcessor. The EntryProcessor allows you to process a peace of code on an entry in an atomic way. This means the cache is doing all the locking for you. Depending of the scope of the problem, this may have an advantage, since this also works in clustered scenarios, which means the locking is cluster wide.
Another idea which comes to my mind is the vetoable eviction. This is a concept EHCache 3 is implementing. By specifying a vetoable eviction policy you can implement a pinning mechanism on your own.

I'm sure that there are multiple solutions for your issue.
I wrote down one of them with using a unique lock for each ietmId:
public class LockManager {
private Map<Integer, Lock> lockMap = new ConcurrentHashMap<>();
public synchronized Lock getOrCreateLockForId(Integer itemId) {
Lock lock;
if (lockMap.containsKey(itemId)) {
System.out.println("Get lock");
lock = lockMap.get(itemId);
} else {
System.out.println("Create lock");
lock = new ReentrantLock();
lockMap.put(itemId, lock);
}
return lock;
}
public synchronized Lock getLockForId(Integer itemId) {
Lock lock;
if (lockMap.containsKey(itemId)) {
System.out.println("get lock");
return lockMap.get(itemId);
} else {
throw new IllegalStateException("First lock, than unlock");
}
}
}
So, instead of using synchronised methods in class Item use LockManager to get Lock by itemId and call lock.lock() after it was retrieved.
Also note that LockManager should have singleton scope and the same instance should be shared across all usages.
Below you can see example of LockManager using:
try {
lockManager.getOrCreateLockForId(itemId).lock();
System.out.println("start doing something" + num);
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("completed doing something" + num);
} finally {
lockManager.getLockForId(itemId).unlock();
}

Related

Java concurrency problem with Servlet requests

What is the right way to solve following problem?
Writing a logic where at a same time 100 reader(Servlet requests) or one writer(Servlet requests) can be accessing critical section for one key in a map(Cache).
If writer comes into the picture in that case all reader should stop there progress and should restart once writer done with critical section processing(Re population cache element for same key).
I implemented one of the solution like in this question, where one instance of Resource class will be associated with single key.
class Resource {
private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
private final Lock rlock = lock.readLock();
private final Lock wlock = lock.writeLock();
void read() { ... /* caller has to hold the read lock */ ... }
void write() { ... /* caller has to hold the write lock */ ... }
Lock readLock() { return rlock; }
Lock writeLock() { return wlock; }
}
Previously I implemented simple logic using Semaphore where I have associated one semaphore instance with single key and used 100 permits for the same and if writer thread is coming into the picture in that case I consumed all remaining permits(drainPermits) and letting all permit free by all readers and putted writer thread in waiting queue. But it leads to starvation to writer.
Other thing I was thinking that using ConcurrentHashMap could solve it? As ConcurrentHashMap have key based locking internally(Segments).
You don't have to expose the locking to the user of the resource, however if you start implementing that pattern you soon discover that you may as well use a ConcurrentHashMap which is actually optimized well for synchronized access
class Resource {
private Cache<Key, Value> yourcache;
private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
private final Lock rlock = lock.readLock();
private final Lock wlock = lock.writeLock();
Value read(Key key) { try {
rlock.lock();
return yourcache.get(key)
} finally {
rlock.unlock();
}
}
void write(Key key) { ... /* similar pattern to above */ ... }
Lock readLock() { return rlock; } //don't expose these at all!
Lock writeLock() { return wlock; }//don't expose these at all!
}

Why not using a try with lock in java?

I've read this topic, and this blog article about try with resources locks, as the question popped in my head.
But actually, what I'd rather like would be a try with lock, I mean without lock instantiation. It would release us from the verbose
lock.lock();
try {
//Do some synchronized actions throwing Exception
} finally {
//unlock even if Exception is thrown
lock.unlock();
}
Would rather look like :
? implements Unlockable lock ;
...
try(lock) //implicitly calls lock.lock()
{
//Do some synchronized actions throwing Exception
} //implicitly calls finally{lock.unlock();}
So it would not be a TWR, but just some boilerplate cleaning.
Do you have any technical reasons to suggest describing why this would not be a reasonable idea?
EDIT : to clarify the difference between what I propose and a simple synchronized(lock){} block, check this snippet :
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class Test {
public static void main(String[] args) {
ReentrantLock locker =new ReentrantLock();
Condition condition = locker.newCondition();
Thread t1 = new Thread("Thread1") {
#Override
public void run(){
synchronized(locker){
try {
condition.await();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println("Thread1 finished");
}
}
} ;
Thread t2 = new Thread("Thread2") {
#Override
public void run(){
synchronized(locker){
Thread.yield();
condition.signal();
System.out.println("blabla2");
}
}
} ;
t1.start();
t2.start();
}
}
Execution will result in a IllegalMonitorStateException, so lock() and unlock() methods are not implicitly called within synchronized block.
If you had to deal with a simple case like that, where the pattern of locking/unlocking was limited to a narrow scope like this, you probably don't want to use the more complicated Lock class and probably should just be using the synchronized keyword, instead. That being said, if for some reason you needed this with the more complicated Lock object, it should be relatively straight-forward to create a wrapper around Lock that implements the AutoCloseable interface to be able to do just that. Example:
class AutoUnlock implements AutoCloseable {
private final Lock lock;
public static AutoUnlock lock(Lock lock) {
lock.lock();
return new AutoUnlock(lock);
}
public static AutoUnlock tryLock(Lock lock) {
if (!lock.tryLock()) {
throw new LockNotAcquiredException();
}
return new AutoUnlock(lock);
}
#Override
public void close() {
lock.unlock();
}
private AutoUnlock(Lock lock) {
this.lock = lock;
}
}
With a wrapper like the above, you could then do:
try (AutoUnlock autoUnlock = AutoUnlock.lock(lock)) {
// ... do whatever that requires the lock ...
}
That being said, the Lock class is typically used for very complicated locking scenarios where this wouldn't be particularly useful. For example, Lock objects may be locked in one function in a class and later unlocked in another function (e.g. locking a row in a database in response to an incoming remote procedure call, and then unlocking that row in response to a later RPC), and thus having such a wrapper or making a Lock AutoCloseable, itself, would be of limited use for the way it is actually used. For more simple scenarios, it's more common to just use an existing concurrent datastructure or use synchronized.
This answer serves to explain the behavior of your edit. The purpose of synchronized is to lock the monitor of the given object when the thread enters the block (waiting if it isn't available) and releasing it when the thread exits the block.
Lock is a higher level abstraction.
Lock implementations provide more extensive locking operations than
can be obtained using synchronized methods and statements.
You can use it to lock across method boundaries. synchronized is not able to do this so a Lock cannot be implemented solely with synchronized and no implementation I've ever seen uses it. Instead, they use other patterns, like compare and swap. They use this to set a state atomically within a Lock object which marks a certain thread as the owner of the lock.
In your code snippet, you try to invoke
condition.signal();
in a thread which does not own the Lock from which the condition was created. The javadoc states
An implementation may (and typically does) require that the current
thread hold the lock associated with this Condition when this method
is called. Implementations must document this precondition and any
actions taken if the lock is not held. Typically, an exception such as
IllegalMonitorStateException will be thrown.
That's what happened here.
Executing
synchronized (lock) {}
makes the current thread lock (and then release) the monitor on the object referenced by lock. Executing
lock.lock();
makes the current thread set some state within the object referenced by lock which identifies it as the owner.

Lock or wait cache load

We need to lock a method responsible for loading database date into a HashMap based cache.
A possible situation is that a second thread tries to access the method while the first method is still loading cache.
We consider the second thread's effort in this case to be superfluous. We would therefore like to have that second thread wait until the first thread is finished, and then return (without loading the cache again).
What I have works, but it seems quite inelegant. Are there better solutions?
private static final ReentrantLock cacheLock = new ReentrantLock();
private void loadCachemap() {
if (cacheLock.tryLock()) {
try {
this.cachemap = retrieveParamCacheMap();
} finally {
cacheLock.unlock();
}
} else {
try {
cacheLock.lock(); // wait until thread doing the load is finished
} finally {
try {
cacheLock.unlock();
} catch (IllegalMonitorStateException e) {
logger.error("loadCachemap() finally {}",e);
}
}
}
}
I prefer a more resilient approach using read locks AND write locks. Something like:
private static final ReadWriteLock cacheLock = new ReentrantReadWriteLock();
private static final Lock cacheReadLock = cacheLock.readLock();
private static final Lock cacheWriteLock = cacheLock.writeLock();
private void loadCache() throws Exception {
// Expiry.
while (storeCache.expired(CachePill)) {
/**
* Allow only one in - all others will wait for 5 seconds before checking again.
*
* Eventually the one that got in will finish loading, refresh the Cache pill and let all the waiting ones out.
*
* Also waits until all read locks have been released - not sure if that might cause problems under busy conditions.
*/
if (cacheWriteLock.tryLock(5, TimeUnit.SECONDS)) {
try {
// Got a lock! Start the rebuild if still out of date.
if (storeCache.expired(CachePill)) {
rebuildCache();
}
} finally {
cacheWriteLock.unlock();
}
}
}
}
Note that the storeCache.expired(CachePill) detects a stale cache which may be more than you are wanting but the concept here is the same, establish a write lock before updating the cache which will deny all read attempts until the rebuild is done. Also, manage multiple attempts at write in a loop of some sort or just drop out and let the read lock wait for access.
A read from the cache now looks like this:
public Object load(String id) throws Exception {
Store store = null;
// Make sure cache is fresh.
loadCache();
try {
// Establish a read lock so we do not attempt a read while teh cache is being updated.
cacheReadLock.lock();
store = storeCache.get(storeId);
} finally {
// Make sure the lock is cleared.
cacheReadLock.unlock();
}
return store;
}
The primary benefit of this form is that read access does not block other read access but everything stops cleanly during a rebuild - even other rebuilds.
You didn't say how complicated your structure is and how much concurrency / congestion you need. There are many ways to address your need.
If your data is simple, use a ConcurrentHashMap or similar to hold your data. Then just read and write in threads regardlessly.
Another alternative is to use actor model and put read/write on the same queue.
If all you need is to fill a read-only map which is initialized from database once requested, you could use any form of double-check locking which may be implemented in a number of ways. The easiest variant would be the following:
private volatile Map<T, V> cacheMap;
public void loadCacheMap() {
if (cacheMap == null) {
synchronized (this) {
if (cacheMap == null) {
cacheMap = retrieveParamCacheMap();
}
}
}
}
But I would personally prefer to avoid any form of synchronization here and just make sure that the initialization is done before any other thread can access it (for example in a form of init method in a DI container). In this case you would even avoid overhead of volatile.
EDIT: The answer works only when initial load is expected. In case of multiple updates, you could try to replace the tryLock by some other form of test and test-and-set, for example using something like this:
private final AtomicReference<CountDownLatch> sync =
new AtomicReference<>(new CountDownLatch(0));
private void loadCacheMap() {
CountDownLatch oldSync = sync.get();
if (oldSync.getCount() == 0) { // if nobody updating now
CountDownLatch newSync = new CountDownLatch(1);
if (sync.compareAndSet(oldSync, newSync)) {
cacheMap = retrieveParamCacheMap();
newSync.countDown();
return;
}
}
sync.get().await();
}

Fine-grained synchronization/locking of method calls based on method parameters

I want to synchronize method calls on basis some id i.e. something like a concurrency Decorator of a given object instance.
For example:
All threads which call the method with param "id1", should execute serially to one another.
All of the rest, which call the method with different argument, say "id2", should execute in parallel to the threads which call the method with param "id1", but again serially to each other.
So in my mind this can be implemented by having a lock (http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/locks/ReentrantLock.html) instance per such method param.
Each time the method is called with the param, the lock instance corresponding to the specific param value (e.g. "id1") would be looked up and the current thread would try to obtain the lock.
Speaking in code:
public class ConcurrentPolicyWrapperImpl implements Foo {
private Foo delegate;
/**
* Holds the monitor objects used for synchronization.
*/
private Map<String, Lock> concurrentPolicyMap = Collections.synchronizedMap(new HashMap<String, Lock>());
/**
* Here we decorate the call to the wrapped instance with a synchronization policy.
*/
#Override
public Object callFooDelegateMethod (String id) {
Lock lock = getLock(id);
lock.lock();
try {
return delegate.delegateMethod(id);
} finally {
lock.unlock();
}
}
protected Lock getLock(String id) {
Lock lock = concurrentPolicyMap.get(id);
if (lock == null) {
lock = createLock();
concurrentPolicyMap.put(id, lock);
}
return lock;
}
}
protected Lock createLock() {
return new ReentrantLock();
}
It seems that this works - I did some performance testing with jmeter and so on.
Still, as we all know concurrency in Java is a tricky thing, I decided to ask for your opinion here.
I can't stop thinking that there could be a better way to accomplish this. For example by using one of the BlockingQueue implementations. What do you think?
I also can't really decide for sure if there is a potential synchronization problem with getting the lock i.e. the protected Lock getLock(String id) method. I am using a synchronized collection, but is that enough? I.e. shouldn't it be something like the following instead of what I currently have:
protected Lock getLock(String id) {
synchronized(concurrentPolicyMap) {
Lock lock = concurrentPolicyMap.get(id);
if (lock == null) {
lock = createLock();
concurrentPolicyMap.put(id, lock);
}
return lock;
}
}
So what do you guys think?
Lock creation issues aside, the pattern is OK except that you may have an unbounded number of locks. Generally people avoid this by creating/using a Striped lock. There is a good/simple implementation in the guava library.
Application area of lock-striping
How to acquire a lock by a key
http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/util/concurrent/Striped.html
Example code using guava implementation:
private Striped<Lock> STRIPPED_LOCK = Striped.lock(64);
public static void doActualWork(int id) throws InterruptedException {
try {
STRIPPED_LOCK.get(id).lock();
...
} finally {
STRIPPED_LOCK.get(id).unlock();
}
}
Though I would personally prefer Guava's Striped<Lock> approach suggested by Keith, just for discussion & completeness, I'd like to point out that using a Dynamic Proxy, or the more generic AOP (Aspect Oriented Programming), is one approach.
So we would define an IStripedConcurrencyAware interface that would serve as the "something like a concurrency Decorator" that you desire, and the Dynamic Proxy / AOP method hijacking based on this interface would de-multiplex the method call into the appropriate Executor / Thread.
I personally dislike AOP (or most of Spring, for that matter) because it breaks the what-you-see-is-what-you-get simplicity of Core Java, but YMMV.

Extending java's ThreadLocal to allow the values to be reset across all threads

After looking at this question, I think I want to wrap ThreadLocal to add a reset behavior.
I want to have something similar to a ThreadLocal, with a method I can call from any thread to set all the values back to the same value. So far I have this:
public class ThreadLocalFlag {
private ThreadLocal<Boolean> flag;
private List<Boolean> allValues = new ArrayList<Boolean>();
public ThreadLocalFlag() {
flag = new ThreadLocal<Boolean>() {
#Override protected Boolean initialValue() {
Boolean value = false;
allValues.add(value);
return value;
}
};
}
public boolean get() {
return flag.get();
}
public void set(Boolean value) {
flag.set(value);
}
public void setAll(Boolean value) {
for (Boolean tlValue : allValues) {
tlValue = value;
}
}
}
I'm worried that the autoboxing of the primitive may mean the copies I've stored in the list will not reference the same variables referenced by the ThreadLocal if I try to set them. I've not yet tested this code, and with something tricky like this I'm looking for some expert advice before I continue down this path.
Someone will ask "Why are you doing this?". I'm working in a framework where there are other threads that callback into my code, and I don't have references to them. Periodically I want to update the value in a ThreadLocal variable they use, so performing that update requires that the thread which uses the variable do the updating. I just need a way to notify all these threads that their ThreadLocal variable is stale.
I'm flattered that there is new criticism recently regarding this three year old question, though I feel the tone of it is a little less than professional. The solution I provided has worked without incident in production during that time. However, there are bound to be better ways to achieve the goal that prompted this question, and I invite the critics to supply an answer that is clearly better. To that end, I will try to be more clear about the problem I was trying to solve.
As I mentioned earlier, I was using a framework where multiple threads are using my code, outside my control. That framework was QuickFIX/J, and I was implementing the Application interface. That interface defines hooks for handling FIX messages, and in my usage the framework was configured to be multithreaded, so that each FIX connection to the application could be handled simultaneously.
However, the QuickFIX/J framework only uses a single instance of my implementation of that interface for all the threads. I'm not in control of how the threads get started, and each is servicing a different connection with different configuration details and other state. It was natural to let some of that state, which is frequently accessed but seldom updated, live in various ThreadLocals that load their initial value once the framework has started the thread.
Elsewhere in the organization, we had library code to allow us to register for callbacks for notification of configuration details that change at runtime. I wanted to register for that callback, and when I received it, I wanted to let all the threads know that it's time to reload the values of those ThreadLocals, as they may have changed. That callback comes from a thread I don't control, just like the QuickFIX/J threads.
My solution below uses ThreadLocalFlag (a wrapped ThreadLocal<AtomicBoolean>) solely to signal the other threads that it may be time to update their values. The callback calls setAll(true), and the QuickFIX/J threads call set(false) when they begin their update. I have downplayed the concurrency issues of the ArrayList because the only time the list is added to is during startup, and my use case was smaller than the default size of the list.
I imagine the same task could be done with other interthread communication techniques, but for what it's doing, this seemed more practical. I welcome other solutions.
Interacting with objects in a ThreadLocal across threads
I'll say up front that this is a bad idea. ThreadLocal is a special class which offers speed and thread-safety benefits if used correctly. Attempting to communicate across threads with a ThreadLocal defeats the purpose of using the class in the first place.
If you need access to an object across multiple threads there are tools designed for this purpose, notably the thread-safe collections in java.util.collect.concurrent such as ConcurrentHashMap, which you can use to replicate a ThreadLocal by using Thread objects as keys, like so:
ConcurrentHashMap<Thread, AtomicBoolean> map = new ConcurrentHashMap<>();
// pass map to threads, let them do work, using Thread.currentThread() as the key
// Update all known thread's flags
for(AtomicBoolean b : map.values()) {
b.set(true);
}
Clearer, more concise, and avoids using ThreadLocal in a way it's simply not designed for.
Notifying threads that their data is stale
I just need a way to notify all these threads that their ThreadLocal variable is stale.
If your goal is simply to notify other threads that something has changed you don't need a ThreadLocal at all. Simply use a single AtomicBoolean and share it with all your tasks, just like you would your ThreadLocal<AtomicBoolean>. As the name implies updates to an AtomicBoolean are atomic and visible cross-threads. Even better would be to use a real synchronization aid such as CyclicBarrier or Phaser, but for simple use cases there's no harm in just using an AtomicBoolean.
Creating an updatable "ThreadLocal"
All of that said, if you really want to implement a globally update-able ThreadLocal your implementation is broken. The fact that you haven't run into issues with it is only a coincidence and future refactoring may well introduce hard-to-diagnose bugs or crashes. That it "has worked without incident" only means your tests are incomplete.
First and foremost, an ArrayList is not thread-safe. You simply cannot use it (without external synchronization) when multiple threads may interact with it, even if they will do so at different times. That you aren't seeing any issues now is just a coincidence.
Storing the objects as a List prevents us from removing stale values. If you call ThreadLocal.set() it will append to your list without removing the previous value, which introduces both a memory leak and the potential for unexpected side-effects if you anticipated these objects becoming unreachable once the thread terminated, as is usually the case with ThreadLocal instances. Your use case avoids this issue by coincidence, but there's still no need to use a List.
Here is an implementation of an IterableThreadLocal which safely stores and updates all existing instances of the ThreadLocal's values, and works for any type you choose to use:
import java.util.Iterator;
import java.util.concurrent.ConcurrentMap;
import com.google.common.collect.MapMaker;
/**
* Class extends ThreadLocal to enable user to iterate over all objects
* held by the ThreadLocal instance. Note that this is inherently not
* thread-safe, and violates both the contract of ThreadLocal and much
* of the benefit of using a ThreadLocal object. This class incurs all
* the overhead of a ConcurrentHashMap, perhaps you would prefer to
* simply use a ConcurrentHashMap directly instead?
*
* If you do really want to use this class, be wary of its iterator.
* While it is as threadsafe as ConcurrentHashMap's iterator, it cannot
* guarantee that all existing objects in the ThreadLocal are available
* to the iterator, and it cannot prevent you from doing dangerous
* things with the returned values. If the returned values are not
* properly thread-safe, you will introduce issues.
*/
public class IterableThreadLocal<T> extends ThreadLocal<T>
implements Iterable<T> {
private final ConcurrentMap<Thread,T> map;
public IterableThreadLocal() {
map = new MapMaker().weakKeys().makeMap();
}
#Override
public T get() {
T val = super.get();
map.putIfAbsent(Thread.currentThread(), val);
return val;
}
#Override
public void set(T value) {
map.put(Thread.currentThread(), value);
super.set(value);
}
/**
* Note that this method fundamentally violates the contract of
* ThreadLocal, and exposes all objects to the calling thread.
* Use with extreme caution, and preferably only when you know
* no other threads will be modifying / using their ThreadLocal
* references anymore.
*/
#Override
public Iterator<T> iterator() {
return map.values().iterator();
}
}
As you can hopefully see this is little more than a wrapper around a ConcurrentHashMap, and incurs all the same overhead as using one directly, but hidden in the implementation of a ThreadLocal, which users generally expect to be fast and thread-safe. I implemented it for demonstration purposes, but I really cannot recommend using it in any setting.
It won't be a good idea to do that since the whole point of thread local storage is, well, thread locality of the value it contains - i.e. that you can be sure that no other thread than your own thread can touch the value. If other threads could touch your thread local value, it won't be "thread local" anymore and that will break the memory model contract of thread local storage.
Either you have to use something other than ThreadLocal (e.g. a ConcurrentHashMap) to store the value, or you need to find a way to schedule an update on the threads in question.
You could use google guava's map maker to create a static final ConcurrentWeakReferenceIdentityHashmap with the following type: Map<Thread, Map<String, Object>> where the second map is a ConcurrentHashMap. That way you'd be pretty close to ThreadLocal except that you can iterate through the map.
I'm disappointed in the quality of the answers received for this question; I have found my own solution.
I wrote my test case today, and found the only issue with the code in my question is the Boolean. Boolean is not mutable, so my list of references wasn't doing me any good. I had a look at this question, and changed my code to use AtomicBoolean, and now everything works as expected.
public class ThreadLocalFlag {
private ThreadLocal<AtomicBoolean> flag;
private List<AtomicBoolean> allValues = new ArrayList<AtomicBoolean>();
public ThreadLocalFlag() {
flag = new ThreadLocal<AtomicBoolean>() {
#Override protected AtomicBoolean initialValue() {
AtomicBoolean value = new AtomicBoolean();
allValues.add(value);
return value;
}
};
}
public boolean get() {
return flag.get().get();
}
public void set(boolean value) {
flag.get().set(value);
}
public void setAll(boolean value) {
for (AtomicBoolean tlValue : allValues) {
tlValue.set(value);
}
}
}
Test case:
public class ThreadLocalFlagTest {
private static ThreadLocalFlag flag = new ThreadLocalFlag();
private static boolean runThread = true;
#AfterClass
public static void tearDownOnce() throws Exception {
runThread = false;
flag = null;
}
/**
* #throws Exception if there is any issue with the test
*/
#Test
public void testSetAll() throws Exception {
startThread("ThreadLocalFlagTest-1", false);
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
//ignore
}
startThread("ThreadLocalFlagTest-2", true);
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
//ignore
}
startThread("ThreadLocalFlagTest-3", false);
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
//ignore
}
startThread("ThreadLocalFlagTest-4", true);
try {
Thread.sleep(8000L); //watch the alternating values
} catch (InterruptedException e) {
//ignore
}
flag.setAll(true);
try {
Thread.sleep(8000L); //watch the true values
} catch (InterruptedException e) {
//ignore
}
flag.setAll(false);
try {
Thread.sleep(8000L); //watch the false values
} catch (InterruptedException e) {
//ignore
}
}
private void startThread(String name, boolean value) {
Thread t = new Thread(new RunnableCode(value));
t.setName(name);
t.start();
}
class RunnableCode implements Runnable {
private boolean initialValue;
RunnableCode(boolean value) {
initialValue = value;
}
#Override
public void run() {
flag.set(initialValue);
while (runThread) {
System.out.println(Thread.currentThread().getName() + ": " + flag.get());
try {
Thread.sleep(4000L);
} catch (InterruptedException e) {
//ignore
}
}
}
}
}

Categories