How to thread safely through List:vector, copyonwritearraylist

Source: Internet
Author: User
Tags concurrentmodificationexception

Multiple ways to traverse a list

Before we talk about how to thread safely through the list, let's look at the ways in which we usually traverse a list.

Way One:
for(int0; i < list.size(); i++) {    System.out.println(list.get(i));}
Way two:
Iterator iterator = list.iterator();while(iterator.hasNext()) {    System.out.println(iterator.next());}
Way three:
for(Object item : list) {    System.out.println(item);}
Mode four (Java 8):
list.forEach(new Consumer<Object>() {    @Override    publicvoidaccept(Object item) {        System.out.println(item);    }});
Mode Five (Java 8 Lambda):
list.forEach(item -> {    System.out.println(item);});

The traversal method of mode one is a very good way to traverse the implementation class of the Randomaccess interface (such as ArrayList).

However, for LinkedList, a list based on a linked list, list.get(i) the performance of the element is poor.

The nature of the mode two and the way 32 is the same, all through the iterator iterator to implement the traversal, the third is the enhanced version of the For loop, can be seen as a simplified form of two.

The same is true of mode four and mode five, all of which are traversed using the new foreach method of Java 8. Mode Five is a simplified form of mode four, which uses lambda expressions.

What happens when you manipulate the list at the same time that you traverse the list?

Experiment with a non-thread-safe ArrayList and traverse the list with a thread. At the same time of traversal, there is one thread that deletes an element from the list. The code is as follows:

 Public Static void Main(string[] args) {//Initialize a list, put 5 elements    Finallist<integer> list =NewArraylist<> (); for(inti =0; I <5;    i++) {list.add (i); }//Line Cheng: Traversing list via iterator    NewThread (NewRunnable () {@Override         Public void Run() { for(intItem:list) {System.out.println ("traverse element:"+ Item);//Because the program runs too fast, sleep here for 1 seconds to slow down the program execution speed                Try{Thread.Sleep ( +); }Catch(Interruptedexception e)                {E.printstacktrace (); }}}). Start ();//Thread Two: Remove an element    NewThread (NewRunnable () {@Override         Public void Run() {//Because the program runs too fast. Sleep here for 1 seconds to slow down the program's execution speed .            Try{Thread.Sleep ( +); }Catch(Interruptedexception e)            {E.printstacktrace (); } list.remove (4); System.out.println ("List.remove (4)"); }}). Start ();}

Execution Result:
traversing elements: 0
traversing elements: 1
List.remove (4)
Exception in Thread "Thread-0" java.util.ConcurrentModificationException

Line Cheng when traversing to the second element, thread two deletes an element. At this point the program has an exception: Concurrentmodificationexception.

Imagine a teacher is going to order the number of all students in the whole class (Threads walk through list), while principals (thread two) call away a few students at the same time. Then the teacher must not go any further.

So we will think of a solution, that is, the headmaster waits for the teacher to finish the students, then call away the students.

That is, thread two waits for the line Cheng to complete before the remove element is completed.

Using a thread-safe vector

ArrayList is non-thread safe. Vector is thread-safe, so is it possible to thread safely through the ArrayList instead of a vector?

In the program:

finalnew ArrayList<>();

Change to:

finalnew Vector<>();

If you try again, you will find that the result is as ArrayList as the concurrentmodificationexception exception.

Why is thread-safe vectors not thread-safe to traverse? In fact the truth is also very easy, see the vector source code can find its very many methods are added synchronized to thread synchronization, such as Add (), remove (), set (), Get (), However, the synchronized method inside the vector does not control the traversal operation. So even a thread-safe vector cannot be thread-safe to traverse.

Assuming that you want the thread to traverse the vector safely, we need to manually add a synchronized lock to the vector while traversing, preventing the remove from traversing at the same time. The equivalent of the headmaster waiting for the teacher to finish the students, then call away students. The code is as follows:

 Public Static void Main(string[] args) {//Initialize a list. Put 5 elements in a    Finallist<integer> list =NewVector<> (); for(inti =0; I <5;    i++) {list.add (i); }//Line Cheng: Traversing list via iterator    NewThread (NewRunnable () {@Override         Public void Run() {//synchronized to lock the list. The remove operation is performed after the pass-through release lock is completed            synchronized(list) { for(intItem:list) {System.out.println ("traverse element:"+ Item);//Because the program runs too fast, sleep here for 1 seconds to slow down the program execution speed                    Try{Thread.Sleep ( +); }Catch(Interruptedexception e)                    {E.printstacktrace (); }}}). Start ();//Thread Two: Remove an element    NewThread (NewRunnable () {@Override         Public void Run() {//Because the program runs too fast, sleep here for 1 seconds to slow down the program execution speed            Try{Thread.Sleep ( +); }Catch(Interruptedexception e)            {E.printstacktrace (); } list.remove (4); System.out.println ("List.remove (4)"); }}). Start ();}

Execution Result:
traversing elements: 0
traversing elements: 1
traversing elements: 2
traversing elements: 3
traversing elements: 4
List.remove (4)

The execution results show list.remove(4) that the action is waiting for the traversal to be completed.

Copyonwritearraylist

Copyonwritearraylist is the implementation class for a list in the Java.util.concurrent package. Copyonwrite means copying at the time of writing. It is assumed that the content of copyonwritearraylist needs to be changed. First, a new list is copied and changed on the new list, and the reference to the original list is then pointed to the new list.

Using Copyonwritearraylist can thread safely through, because if another thread changes the list while traversing, it will actually copy a new list change. Without affecting the list that is currently being traversed.

The equivalent of the headmaster wants to shout away from the class or join the students. The student is required to take all the students to a new classroom, and the teacher takes a snapshot of the previous class to count the students in the photo.

 Public Static void Main(string[] args) {//Initialize a list, put 5 elements    Finallist<integer> list =NewCopyonwritearraylist<> (); for(inti =0; I <5;    i++) {list.add (i); }//Line Cheng: Traversing list via iterator    NewThread (NewRunnable () {@Override         Public void Run() { for(intItem:list) {System.out.println ("traverse element:"+ Item);//Because the program runs too fast, sleep here for 1 seconds to slow down the program execution speed                Try{Thread.Sleep ( +); }Catch(Interruptedexception e)                {E.printstacktrace (); }}}). Start ();//Thread Two: Remove an element    NewThread (NewRunnable () {@Override         Public void Run() {//Because the program runs too fast, sleep here for 1 seconds to slow down the program execution speed            Try{Thread.Sleep ( +); }Catch(Interruptedexception e)            {E.printstacktrace (); } list.remove (4); System.out.println ("List.remove (4)"); }}). Start ();}

Execution Result:
traversing elements: 0
traversing elements: 1
List.remove (4)
traversing elements: 2
traversing elements: 3
Traversing elements: 4

As can be seen from the above execution results, although list.remove(4) an element has been removed, the result of the traversal still exists for that element. It can be seen that the traversed and remove are two different lists.

Thread-Safe List.foreach

The List.foreach method is a new method of Java 8, and the main purpose is to have the list support for Java 8: a lambda expression.

Because the Foreach method is a method of the list, it is different from traversing the list outside the list. The Foreach method is equivalent to the list's own traversal method. So it is free to control thread safety.

We look at the source code of the Foreach method of the thread-safe vector:

publicsynchronizedvoidforEachsuper E> action) {    ...}

The Foreach method that can see vectors adds synchronized to control thread-safe traversal, which means that the foreach method of the vector can be safely traversed by the thread .

The following can be tested:

 Public Static void Main(string[] args) {//Initialize a list, put 5 elements    Finallist<integer> list =NewVector<> (); for(inti =0; I <5;    i++) {list.add (i); }//Line Cheng: Traversing list via iterator    NewThread (NewRunnable () {@Override         Public void Run() {List.foreach (item, {SYSTEM.OUT.PRINTLN ("traverse element:"+ Item);//Because the program runs too fast, sleep here for 1 seconds to slow down the program execution speed                Try{Thread.Sleep ( +); }Catch(Interruptedexception e)                {E.printstacktrace ();        }            }); }}). Start ();//Thread Two: Remove an element    NewThread (NewRunnable () {@Override         Public void Run() {//Because the program runs too fast, sleep here for 1 seconds to slow down the program execution speed            Try{Thread.Sleep ( +); }Catch(Interruptedexception e)            {E.printstacktrace (); } list.remove (4); System.out.println ("List.remove (4)"); }}). Start ();}

Execution Result:
traversing elements: 0
traversing elements: 1
traversing elements: 2
traversing elements: 3
traversing elements: 4
List.remove (4)

Reprint please specify the original address: http://xxgblog.com/2016/04/02/traverse-list-thread-safe/

How to thread safely through List:vector, copyonwritearraylist

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.