0

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?

graczun
  • 572
  • 1
  • 5
  • 16
  • Look through the Java API especially the java.util.concurrent.* package and take it from there. – Caleryn Oct 15 '13 at 14:18

5 Answers5

3

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(...).

Narendra Pathai
  • 41,187
  • 18
  • 82
  • 120
  • 1
    Just using the `Collections.synchronizedList` won't magically provide you thread safety. In case of composite operations (i.e. check-then-modify) you have to synchronize manually. –  Oct 15 '13 at 14:42
  • @pavelrappo Yes I agree, I missed that part. Thanks added that too :) – Narendra Pathai Oct 15 '13 at 19:22
2

You can use

List myList = Collections.synchronizedList(new ArrayList());
Konstantin Yovkov
  • 62,134
  • 8
  • 100
  • 147
2

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.

Community
  • 1
  • 1
Jason Braucht
  • 2,358
  • 19
  • 31
1

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

Keerthivasan
  • 12,760
  • 2
  • 32
  • 53
1

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.

Cruncher
  • 7,641
  • 1
  • 31
  • 65
  • I wouldn't generally recommend concurrency primitives (especially after Java 6's concurrency package), unless: 1) There's no built-in functionality for what you're after; 2) Performance is critical (profile it!); and 3) You really grok concurrency enough to write a bug-free implementation. None of these sound like the case here - a `BlockingQueue` would likely do the job, for instance. – Andrzej Doyle Oct 15 '13 at 14:38
  • @AndrzejDoyle I generally stick to primitives, that's just my preference though. My first clash with synchronization was in Operating Systems class. There was no `BlockingQueue` there. Understanding under-the-hood never hurt anybody. However, I perfectly understand your point, but I believe this adds value. – Cruncher Oct 15 '13 at 14:44
  • @AndrzejDoyle `java.util.concurrent` was brought by 1.5 (if that's the package you're talking about). –  Oct 15 '13 at 14:48
  • @Cruncher I agree, it's great to understand how things work. It's just that concurrency (moreso than other things) is *hard*, and so there's even less incentive to reinvent the wheel - plus there's a lot of decent wheels about the place. Maybe I'm overly harsh, but I wouldn't recommend someone use primitives unless I knew they had solid knowledge. Otherwise it's a recipe for bug-ridden, temperamental, "it works on my machine" code. – Andrzej Doyle Oct 15 '13 at 15:10