安全でないコレクション
シングルスレッドアプリケーションでは、通常、new ArrayList()
繰り返し可能なデータを格納するためのリストコレクションを指定するために採用されます。
ただし、マルチスレッドでは、予期しない問題が頻繁に発生します。コードは次のとおりです。
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();
}
}
}
その操作の結果は次のとおりです。
同じオブジェクト情報のセットのマルチスレッド操作java.util.ConcurrentModificationException
。多くの場合、異常なエラーメッセージが表示されます。
Javaで提供されるセキュリティ対策
Java言語では、新しいリストコレクションとjava.util.Vector
クラスが提供されます。詳細については、次のコードを参照してください。
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();
}
}
}
実行中のログは次のとおりです。エラーメッセージ
は表示されませんjava.util.ConcurrentModificationException
。
データの安全な運用が保証されるのはなぜですか?
撮影
synchronized
方法の発信者ロックの実装のため、追加操作の安全性を確保するために、マルチスレッド!
JUCの下でのセーフリストコレクション
JUCパッケージでは、安全なコレクションを作成する方法がいくつかあります。
- 方法一: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();
}
}
}
基盤となるソースコード実装ロジックを表示する
着信リストコレクションのタイプを判別し、タイプがそうであるかどうかを判別し
java.util.RandomAccess
、そうである場合はjava.util.Collections.SynchronizedRandomAccessList
構築セットを使用し、そうでない場合はjava.util.Collections.SynchronizedList
構築セットを使用します。
ソースコード内の対応する追加操作ロジックは次のとおりです。
synchronized
コードブロックを同期する方法を取り、データの追加操作のロックを実現してください!
- メソッド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();
}
}
}
ソースコードの
概要は次のとおりです。明らかに、ロジックは次のとおりです。
1. addメソッドを呼び出した後、
java.util.concurrent.locks.ReentrantLock
オブジェクト情報を取得します。
2、lock.lock()
ロックを取得するために呼び出します!
3.元の配列オブジェクトをコピーし、元の配列+1のサイズで新しい配列を作成します。
4.新しいデータを新しい配列に配置します。
5.最後に操作を行うと、ロックが解除されます。
パフォーマンスの側面
JUCパッケージでのロック操作は、同期よりもパフォーマンスが優れています。