6

It looks like when programming in Java we are not suppose to use Vectors anymore when threads are involved.

What class should I use instead of a Vector when using threads?

import java.util.Vector;
Vector<String> v = new Vector<String>();
Matt Ball
  • 354,903
  • 100
  • 647
  • 710
VSH3R
  • 61
  • 1
  • 1
  • 2

5 Answers5

17

It looks like when programming in Java we are not suppose to use Vectors anymore when threads are involved.

You need to understand why using Vector is considered to be a bad thing in most contexts. The reasons are:

  • Vector synchronizes on every operation. Most contexts do not require fine-grained synchronization, and as such it is an unwanted performance overhead.

  • The Vector.elements() method returns an Enumeration which does not have fail-fast semantics.

Bringing this back to your question. The alternatives depend on what your threads are trying to do:

  • If the use-case does not require synchronization at all, use ArrayList, or LinkedList. You would typically use these if:

    • The list is thread-confined; i.e. only one thread ever can access it.
    • The list requires coarse-grained synchronization; i.e. exclusive access while performing a sequence of operations. In this case, you would typically create a custom class with an embedded (say) ArrayList that is not exposed in the custom classes API.
  • If the use-case requires fine-grained synchronization, Collections.synchronizedList wrapper is equivalent to a Vector. For example:

    List<Integer> vec = Collections.synchronizedList(new ArrayList<Integer>());
    

    Alternatively, you could stick with Vector and avoid using the elements() operation.

  • A CopyOnWriteArrayList list has the advantage that its iterator supports concurrent modification ... in a sense. It also scales better if your application mostly performs read the list. Read operations don't need to explicitly synchronize at all, and typically just need to read a single volatile once. But the flip side is that write operations do synchronize, and are significantly more expensive than a "normal" ArrayList.

The other problem with Vector and the Collections.synchronizedList wrapper is that some use-cases require coarser synchronization; e.g. testing a list's size and conditionally adding an element in a single synchronized operation. The Queue and Deque classes provide higher level abstractions that deal with this kind of thing ... for the use-cases involving passing work asynchronously from one thread to another.


The bottom line is that there is not one-size-fits-all solution. You need to understand the concurrency characteristics of your application design, and choose your data structures accordingly.


Finally, if you are programming for Java ME, you may be stuck with using Vector, depending on what J2ME profile you are targeting.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • @VSH3R See http://stackoverflow.com/questions/703990/why-is-c-list-not-thread-safe and http://www.ibm.com/developerworks/java/library/j-jtp09263.html. – tiago2014 Mar 09 '11 at 00:01
5
List<String> list = Collections.synchronizedList(new ArrayList<String>());
Tomasz Nurkiewicz
  • 334,321
  • 69
  • 703
  • 674
5

For thread-unsafe cases, use ArrayList.

For thread-safe cases, use whatever is most appropriate in your case, CopyOnWriteArrayList, Queue, BlockingDeque, etc. To advice more, we need to know how you manipulate things with your collection.

I would recommend against using Collections.synchronizedList(...) wrapper as it might not scale well enough (unless you don't care much about scalability). But it all depends on your context.

mindas
  • 26,463
  • 15
  • 97
  • 154
  • Could you explain why `Collections.synchronizedList(...)` doesn't scale? – corsiKa Mar 08 '11 at 22:28
  • 1
    If your usage pattern is 99% reads and 1% writes, CopyOnWriteArrayList provides better performance (read COWAL javadoc). But it all depends on the usage pattern. – mindas Mar 08 '11 at 22:30
  • Fair enough - an interesting class. I'm not 100% sure I agree with it (i.e. it solves a problem that could probably be solved by using a better design) but sometimes what's ideal and what's practical are two different things. +1 – corsiKa Mar 08 '11 at 22:38
  • 1
    I was careful enough not to say this applies for all scenarios, I think that's very important point. Studying your problem more thoroughly has never made any damage :) – mindas Mar 08 '11 at 22:41
-1

array, but if you don't know the size, use an implementation of concurrentmap

necromancer
  • 23,916
  • 22
  • 68
  • 115
  • assuming you want fast random access to elements (which is why list would be a bad idea) – necromancer Mar 08 '11 at 22:22
  • The difference is: a Map offers random access by key, a List offers random access by index (more or less efficiently). – Paŭlo Ebermann Mar 08 '11 at 22:30
  • you mean map offers O(log(n)) access whereas List offers O(1)? then it confounds the discussion to call it a list -- it is an array masquerading in a list interface. if you know the size, an array is clearly the best, easiest to understand choice. ONLY if you don't know the size your choice is between a map, or grow-able arrays offering somewhat unpredictable performance in a multi-threaded situation. – necromancer Mar 08 '11 at 23:10
-2

Use Lists and synchronize them like

List<?> list = Collections.synchronizedList(new ArrayList<?>());
Buhake Sindi
  • 87,898
  • 29
  • 167
  • 228