English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
The List interface implementation of a variable-size array. It implements all optional list operations and allows all elements including null. In addition to implementing the List interface, this class provides some methods to operate on the size of the array used internally to store the list. (This class is roughly equivalent to the Vector class, except that this class is not synchronized.) The size, isEmpty, get, set, iterator, and listIterator operations run in constant time. The add operation runs in amortized constant time, which means that adding n elements requires O(n) time. All other operations run in linear time (to put it simply). Compared to the constant factors used in the LinkedList implementation, this implementation has lower constant factors. Each ArrayList instance has a capacity. The capacity is the size of the array used to store the list elements. It is always at least as large as the size of the list. As elements are added to the ArrayList, its capacity also grows automatically. The details of the growth strategy are not specified because it is not just adding elements that brings the amortized constant time overhead. Before adding a large number of elements, the application can use the ensureCapacity operation to increase the capacity of the ArrayList instance. This can reduce the number of incremental reallocations.
Note that this implementation is not synchronized.
If multiple threads access a single ArrayList instance, and at least one thread modifies the list structurally, it must be synchronized externally. (Structural modifications are any addition or deletion of one or more elements, or explicit adjustment of the size of the underlying array; merely setting the value of an element is not a structural modification.) This is generally accomplished by synchronizing on the object naturally encapsulating the list. If no such object exists, the list should be wrapped using the Collections.synchronizedList method. This is best done at the time of creation to prevent accidental unsynchronized access to the list:
Listlist = Collections.synchronizedList(newArrayList(...));
The iterators returned by this iterator and listIterator methods are rapid-failure: after creating the iterator, unless the list is modified structurally through the iterator's own remove or add method, the iterator will throw ConcurrentModificationException at any time and in any way. Therefore, in the face of concurrent modifications, the iterator will quickly fail completely, rather than risking any arbitrary behavior at an uncertain time in the future.
Note that the rapid-failure behavior of iterators cannot be guaranteed, because generally, it is impossible to make any hard guarantees about whether there are unsynchronized concurrent modifications. The rapid-failure iterator will try its best to throw ConcurrentModificationException. Therefore, writing a program that depends on this exception for the correctness of this type of iterator is incorrect: the rapid-failure behavior of iterators should only be used to detect bugs.
As shown above, now we establish a list collection, one thread performs write operations on the collection, and another thread performs deletion operations
import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Random; public class MyArrayList { /** * Create a list, one thread writes and one thread reads; the iterators returned by iterator and listIterator methods are fail-fast */ public void readWrite() { List<Integer> nums = new ArrayList<Integer>(); List<Integer> synNums = Collections.synchronizedList(nums); //Start the writing thread new WriteListThread(synNums).start(); //Start the deletion thread new DeleteListThread(synNums).start(); } public static void main(String[] args) { new MyArrayList().readWrite(); } } class WriteListThread extends Thread { private List<Integer> nums; public WriteListThread(List<Integer> nums) { super(“WriteListThread”); this.nums = nums; } // Keep writing elements1 public void run() { while (true) { nums.add(new Random().nextint(1000)); System.out.println(Thread.currentThread().getName()); } } } class DeleteListThread extends Thread { private List<Integer> nums; public DeleteListThread(List<Integer> nums) { super(“DeleteListThread”); this.nums = nums; } // Delete the first element public void run() { while (true) { try{ System.out.println(Thread.currentThread().getName()+:"+nums.remove(0)); } catch(Exception e){ continue ; } } } }
By using List<Integer> synNums = Collections.synchronizedList(nums); you can synchronize atomic operations, but why does the official API example require manual synchronization?
List list = Collections.synchronizedList(new ArrayList()); synchronized(list) { Iterator i = list.iterator(); // Must be in synchronized block while (i.hasNext()) foo(i.next()); }
View the source code of Collections.synchronizedList
SynchronizedCollection(Collection<E> c) { if (c==null) throw new NullPointerException(); this.c = c; mutex = this; }
import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Random; public class MyArrayList { /** * Create a list, one thread writes and one thread reads; the iterators returned by iterator and listIterator methods are fail-fast */ public void readWrite() { List<Integer> nums = new ArrayList<Integer>(); List<Integer> synNums = Collections.synchronizedList(nums); //Start the writing thread new WriteListThread(synNums).start(); //Start the deletion thread new DeleteListThread(synNums).start(); } public static void main(String[] args) { new MyArrayList().readWrite(); } } class WriteListThread extends Thread { private List<Integer> nums; public WriteListThread(List<Integer> nums) { super("WriteListThread"); this.nums = nums; } // Keep writing elements1 public void run() { while (true) { nums.add(new Random().nextint(1000)); System.out.println(Thread.currentThread().getName()); } } } class DeleteListThread extends Thread { private List<Integer> nums; public DeleteListThread(List<Integer> nums) { super("DeleteListThread"); this.nums = nums; } // Delete the first element public void run() { while (true) { try{ System.out.println(Thread.currentThread().getName()+:"+nums.remove(0)); } catch(Exception e){ continue ; } } } }
It can be seen that for synchronized operations on collections, in addition to using the synchronized wrapper utility class of Collections, non-atomic operations also require manual synchronization by the user
As shown below, add a thread to read the collection
class ReadListThread extends Thread { private List<Integer> nums; public ReadListThread(List<Integer> nums) {}} super(“ReadListThread”); this.nums = nums; } // Keep reading elements, non-atomic operations need to be manually locked public void run() { while (true) { //Sleep, hand over the lock to other threads try { Thread.sleep(1000); } catch (InterruptedException e1) { e1.printStackTrace(); } synchronized (nums) { if (nums.size() > 100) { Iterator<Integer> iter = nums.iterator(); while (iter.hasNext()) { System.out.println(Thread.currentThread().getName() + :" + iter.next()); ; } } else{ try { nums.wait(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } } } }
Summary
This is the full content of the detailed explanation of thread synchronization code in the Java collection framework. I hope it will be helpful to everyone. Those who are interested can continue to read other related topics on this site. Welcome to leave a message if there are any shortcomings. Thank you for your support to this site!
Declaration: The content of this article is from the network, and the copyright belongs to the original author. The content is contributed and uploaded by Internet users spontaneously. This website does not own the copyright, has not been manually edited, and does not assume relevant legal liability. If you find any content suspected of copyright infringement, please send an email to: notice#oldtoolbag.com (Please replace # with @ when sending an email to report abuse, and provide relevant evidence. Once verified, this site will immediately delete the content suspected of infringement.)