views:

111

answers:

4

I have this situation:

web application with cca 200 concurent requests (Threads) are in need to log something to local filesystem. I have one class to which all threads are placing their calls, and that class internally stores messages to one Array (Vector or ArrayList) which then in turn will be written to filesystem.

Idea is to return from thread's call ASAP so thread can do it's job as fast as possible, what thread wanted to log can be written to filesystem later, it is not so crucial.

So, that class in turn removes first element from that list and writes it to filesystem, while in real time there is 10 or 20 threads which are appending new logs at the end of that list.

I would like to use ArrayList since it is not synchronized and therefore thread's calls will last less, question is:

am I risking deadlocks / data loss? Is it better to use Vector since it is thread safe? Is it slower to use Vector?

+2  A: 

Are you limitted to particular (old) java version? It not please consider using java.util.concurrent.LinkedBlockingQueue for this kind of stuff. It's really worth looking at java.util.concurrent.* package when dealing with concurrency.

Piotr Maj
+1 BlockingQueues are the way to go for producer/consumer pattern.
Markus Kull
+13  A: 

Actually both ArrayList and Vector are very bad choices here, not because of synchronization (which you would definitely need), but because removing the first element is O(n).

The perfect data structure for your purspose is the ConcurrentLinkedQueue: it offers both thread safety (without using synchronization), and O(1) adding and removing.

Michael Borgwardt
`ArrayDeque` also gives O(1), but probably faster though without the thread-safety.
Tom Hawtin - tackline
A: 

There actually is a marginal difference in performance between a sychronizedlist and a vector. (http://www.javacodegeeks.com/2010/08/java-best-practices-vector-arraylist.html)

Kurt Du Bois
A: 

Vector is worse than useless. Don't use it even when using multithreading. A trivial example of why it's bad is to consider two threads simultaneously iterating and removing elements on the list at the same time. The methods size(), get(), remove() might all be synchronized but the iteration loop is not atomic so - kaboom. One thread is bound to try removing something which is not there, or skip elements because the size() changes.

Instead use synchronized() blocks where you expect two threads to access the same data.

private ArrayList myList;

void removeElement(Object e)
{
  synchronized (myList) {
    myList.remove(e);
  }
}

Java 5 provides explicit Lock objects which allow more finegrained control, such as being able to attempt to timeout if a resource is not available in some time period.

private final Lock lock = new ReentrantLock();
private ArrayList myList;

void removeElement(Object e) {
{
  if (!lock.tryLock(1, TimeUnit.SECONDS)) {
    // Timeout
    throw new SomeException();
  }
  try {
    myList.remove(e);
  }
  finally {
    lock.unlock();
  }
}
locka