Dalam aplikasi berbenang tunggal, ArrayList() baharu biasanya digunakan untuk menentukan koleksi Senarai untuk menyimpan data boleh berulang.
Walau bagaimanapun, di bawah pelbagai benang, masalah yang tidak dijangka sering berlaku seperti berikut:
import java.util.*; public class ListTest { public static void main(String[] args) throws InterruptedException { // 创建list集合 //List<String> lists = Arrays.asList("1", "2", "3"); // 不安全 List<String> lists = new ArrayList<>(); // 开启十个线程增加数据 for (int i = 1; i <= 40; i++) { new Thread(()->{ lists.add(UUID.randomUUID().toString().substring(0,5)); System.out.println(Thread.currentThread().getName()+"=="+lists); },String.valueOf(i)).start(); } } }
Apabila berbilang rangkaian beroperasi pada koleksi maklumat objek yang sama, java.util.ConcurrentModificationException selalunya. berlaku maklumat.
Dalam bahasa java, koleksi Senarai baharu, kelas java.util.Vector, disediakan untuk butiran, lihat kod berikut:
import java.util.*; public class ListTest { public static void main(String[] args) throws InterruptedException { // 创建list集合 //List<String> lists = Arrays.asList("1", "2", "3"); // 不安全 //List<String> lists = new ArrayList<>(); List<String> lists = new Vector<>(); // 开启十个线程增加数据 for (int i = 1; i <= 40; i++) { new Thread(()->{ lists.add(UUID.randomUUID().toString().substring(0,5)); System.out.println(Thread.currentThread().getName()+"=="+lists); },String.valueOf(i)).start(); } } }
Tidak akan ada mesej ralat java.util.ConcurrentModificationException.
Mengapa kami boleh memastikan operasi data yang selamat?
menggunakan disegerakkan untuk mengunci pemanggil pelaksanaan kaedah untuk memastikan keselamatan berbilang benang operasi tambah!
Di bawah pakej JUC, cara berikut untuk membuat koleksi keselamatan disediakan.
Kaedah 1: Collections.synchronizedList(new ArrayList<>());
import java.util.*; public class ListTest { public static void main(String[] args) throws InterruptedException { List<String> lists = Collections.synchronizedList(new ArrayList<>()); // 开启十个线程增加数据 for (int i = 1; i <= 40; i++) { new Thread(()->{ lists.add(UUID.randomUUID().toString().substring(0,5)); System.out.println(Thread.currentThread().getName()+"=="+lists); },String.valueOf(i)).start(); } } }
Lihat logik pelaksanaan kod sumber yang mendasari
Tentukan jenis koleksi senarai masuk dan tentukan sama ada jenisnya ialah java.util.RandomAccess Jika ya, gunakan java.util.Collections.SynchronizedRandomAccessList untuk membina koleksi. Jika tidak, gunakan java.util.Collections.SynchronizedList membina koleksi.
Logik operasi tambah yang sepadan dalam kod sumber adalah seperti berikut:
Gunakan blok kod penyegerakan yang disegerakkan untuk menambah Operasi data untuk mencapai penguncian!
Kaedah 2: new CopyOnWriteArrayList();
import java.util.*; import java.util.concurrent.CopyOnWriteArrayList; public class ListTest { public static void main(String[] args) throws InterruptedException { List<String> lists = new CopyOnWriteArrayList<>(); // 开启十个线程增加数据 for (int i = 1; i <= 40; i++) { new Thread(()->{ lists.add(UUID.randomUUID().toString().substring(0,5)); System.out.println(Thread.currentThread().getName()+"=="+lists); },String.valueOf(i)).start(); } } }
Pengenalan dalam kod sumber adalah seperti berikut:
Jelas sekali, logiknya adalah seperti berikut:
Selepas memanggil kaedah tambah, dapatkan java.util .concurrent.locks .Maklumat objek ReentrantLock.
Panggil lock.lock() untuk mendapatkan kunci!
Salin objek tatasusunan asal dan buat tatasusunan baharu dengan saiz tatasusunan asal + 1.
Masukkan data baharu ke dalam tatasusunan baharu.
Sebarang operasi akhirnya akan melepaskan kunci!
Operasi Lock di bawah pakej JUC mempunyai prestasi yang lebih baik daripada yang disegerakkan!
Atas ialah kandungan terperinci Bagaimanakah Java JUC mengendalikan koleksi kelas keselamatan Senarai?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!