Reputation: 582
I want to create a static arrayList for communication between 3 threads: 1. thread will add some data to list; 2. thread will remove data from list; 3. thread (timer every 3 sec) will check if size of list equals 0, and if no print all object of this list.
I'm wondereing what would happen if more than 1 thread will try to access this list at same time (for example timer will check size of list at same time when second thread will be removeing object from list). I guess that i have to synchronize this list, but have no idea how to do that. Can you give me some advise?
Upvotes: 0
Views: 209
Reputation: 41935
I'm wondereing what would happen if more than 1 thread will try to access this list at same time
Firstly ArrayList
is not thread-safe, so you should not use it directly.
One possibility is to use Collections.synchronizedList(...);
which provides you thread safety but will hamper concurrency.
Your requirement seems to be like a Queue
, so you should use BlockingQueue
for that, e.g LinkedBlockingQueue
which is thread-safe.
NOTE:
Compound operations on list will still be unsafe if you use Collections.synchronizedList(...)
.
Upvotes: 3
Reputation: 2368
ArrayList
is not thread-safe. You will need to handle the synchronization by yourself or the results will be unpredictable.
As suggested in the related question: How do I make my arraylist thread safe you could use Collections.synchronizedList(...)
to obtain a thread-safe version of your List
The javadoc gives an example of how to utilize the List
returned by that method.
List list = Collections.synchronizedList(new ArrayList());
...
synchronized (list) {
Iterator i = list.iterator(); // Must be in synchronized block
while (i.hasNext())
foo(i.next());
}
Other solutions have already suggested this, but using this approach has a potential performance penalty since the synchronization blocks concurrent access to the List
. This will ultimately limit the rate at which you are able to add & remove data from the backing List
.
Upvotes: 2
Reputation: 7812
Better yet, using concurrency primitives (wait, notify, and synchronized) you can have the printing thread wait, and only wake up after one of the other threads actually changed the ArrayList. This has the advantage of not printing when there's no change, and being woken up immediately when a change happens. You may still get false wake-ups, but can be coded around if it's a problem.
In printing thread:
synchronized(lock)
{
while(true/*or some boolean to indicate you're done*/)
{
lock.wait();
//print list
}
}
In a thread that edits the list:
synchronized(lock)
{
//modify list
lock.notify();
}
You can also do lock.wait(3000);
to print after 3 seconds anyway even if no change happens.
Upvotes: 1
Reputation: 12880
This code snippet will help you in the right direction
//have a lock Object
private static final Object lock = new Object();
// your list
private static List list = null
//synchronized on lock object. this will allow only one thread at a time
synchronized(lock){
//access,add to, remove from list
}
By this way, you can make sure there is only one thread at a time accessing your list
Upvotes: 1
Reputation: 62864
You can use
List myList = Collections.synchronizedList(new ArrayList());
Upvotes: 2