Buka baris pertama ulasan dalam kaedah utama dan laksanakannya beberapa kali Anda akan melihat maklumat pengecualian seperti berikut: ???
Ini adalah pengecualian pengubahsuaian serentak. operasi. Di samping itu, Pada masa ini, satu utas juga masuk untuk melaksanakan operasi tambah, dan utas ketiga masuk untuk melaksanakan operasi dapatkan Akibatnya, bacaan dan penulisan tidak dapat disegerakkan, dan hasilnya akhirnya meletup semasa mencetak.
Penyelesaian adalah dengan melihat baris komen yang tinggal dalam kod.
package test.notsafe; import java.util.*; import java.util.concurrent.CopyOnWriteArrayList; /** * 演示ArrayList的线程不安全问题及解决方案 */ public class ThreadDemo2 { public static void main(String[] args) { //List<String> list = new ArrayList<>(); //解决方法1:使用Vector //List<String> list = new Vector<>(); //解决方法2:Collections //List<String> list = Collections.synchronizedList(new ArrayList<>()); //解决方法3:CopyOnWriteArrayList List<String> list = new CopyOnWriteArrayList<>(); for (int i = 0; i < 10; i++) { new Thread(() -> { list.add(UUID.randomUUID().toString().substring(0,8)); System.out.println(list); },String.valueOf(i)).start(); } } }
Penjelasan ringkas tentang cara CopyOnWriteArrayList menyelesaikan masalah tidak selamat benang: Lihat sahaja kaedah add(E e) dalam kod sumber:
public boolean add(E e) { final ReentrantLock lock = this.lock; lock.lock(); try { Object[] elements = getArray(); int len = elements.length; Object[] newElements = Arrays.copyOf(elements, len + 1); newElements[len] = e; setArray(newElements); return true; } finally { lock.unlock(); } }
CopyOnWriteArrayList ini berada dalam Sebelum melakukan operasi tambah, kunci dahulu, kemudian dapatkan bekas koleksi ArrayList asal melalui getArray(), dan kemudian panggil kaedah Arrays.copyOf untuk menyalin bekas asal ke dalam bekas baharu, kerana ia perlu ditambah (panjangnya secara semula jadi ialah +1) , dan kemudian tambah elemen pada bekas baharu ini Selepas penambahan selesai, panggil kaedah setArray untuk menghalakan rujukan bekas asal ke bekas baharu ini. Kemudian kelebihan melakukan ini ialah: tambah elemen dalam bekas baharu, apa sahaja bekas asal sepatutnya, dan jika utas lain ingin mendapatkan dan membaca elemen, mereka masih membaca daripada bekas asal (iaitu, berbilang utas boleh dibaca serentak) ; dan Jika utas lain ingin menambah, mereka perlu menunggu utas lain selesai dan kemudian halakan rujukan bekas asal ke bekas baharu.
Bekas CopyOnWrite ialah dua bekas berbeza ketika membaca dan menulis, dan mereka juga menggunakan idea pengasingan membaca dan menulis.
Jika ia adalah HashSet baharu di sini, pengecualian pengubahsuaian serentak yang sama seperti ArrayList di atas mungkin masih berlaku. Lihat komen dalam kod untuk penyelesaiannya.
package test.notsafe; import java.util.Collections; import java.util.HashSet; import java.util.Set; import java.util.UUID; import java.util.concurrent.CopyOnWriteArraySet; /** * 演示HashSet的线程不安全问题及解决方案 */ public class ThreadDemo3 { public static void main(String[] args) { //Set<String> set = new HashSet<>(); //解决方法1:Collections //Set<String> set = Collections.synchronizedSet(new HashSet<>()); //解决方法2:CopyOnWriteArraySet Set<String> set = new CopyOnWriteArraySet<>(); for (int i = 0; i < 20; i++) { new Thread(() -> { set.add(UUID.randomUUID().toString().substring(0,8)); System.out.println(set); },String.valueOf(i)).start(); } } }
package test.notsafe; import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; /** * 演示HashMap的线程不安全问题及解决方案 */ public class ThreadDemo4 { public static void main(String[] args) { //Map<String,Object> map = new HashMap<>(); //解决方法1:Collections //Map<String,Object> map = Collections.synchronizedMap(new HashMap<>()); //解决方法2:ConcurrentHashMap Map<String,Object> map = new ConcurrentHashMap<>(); for (int i = 0; i < 10; i++) { String key = String.valueOf(i); new Thread(() -> { map.put(key,UUID.randomUUID().toString().substring(0,8)); System.out.println(map); },String.valueOf(i)).start(); } } }
Atas ialah kandungan terperinci Bagaimana untuk memastikan keselamatan benang ArrayList, HashSet dan HashMap dalam persekitaran berbilang benang berkonkurensi tinggi Java?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!