方法一:使用同步包装器
- 描述:Java提供了
Collections
类的静态方法来创建线程安全的集合包装器,例如Collections.synchronizedList
、Collections.synchronizedMap
等。这些方法返回一个同步的集合,对该集合的所有操作都被同步,以确保线程安全。
- 示例:
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class SynchronizedListExample {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
List<String> synchronizedList = Collections.synchronizedList(list);
// 多线程操作synchronizedList
Thread thread1 = new Thread(() -> {
synchronizedList.add("element1");
});
Thread thread2 = new Thread(() -> {
synchronizedList.add("element2");
});
thread1.start();
thread2.start();
try {
thread1.join();
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(synchronizedList);
}
}
- 使用场景:适用于需要简单地将现有的非线程安全集合转换为线程安全集合,并且对性能要求不是特别高的场景。例如,在一些小型的多线程应用程序中,对集合的操作频率不是特别高的情况下可以使用。
方法二:使用并发集合类
- 描述:Java并发包(
java.util.concurrent
)提供了一些线程安全的集合类,如CopyOnWriteArrayList
、ConcurrentHashMap
等。这些集合类针对多线程环境进行了优化,通常具有更好的性能。
CopyOnWriteArrayList
:在修改操作(如添加、删除元素)时,会创建一个底层数组的副本,在副本上进行修改,然后将新数组赋值给原数组。读操作则直接读取原数组,不需要加锁,因此读操作性能较高,但写操作相对较慢。
ConcurrentHashMap
:采用分段锁机制,允许多个线程同时访问不同的段,提高了并发性能。
- 示例 - CopyOnWriteArrayList:
import java.util.Iterator;
import java.util.concurrent.CopyOnWriteArrayList;
public class CopyOnWriteArrayListExample {
public static void main(String[] args) {
CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();
Thread thread1 = new Thread(() -> {
list.add("element1");
});
Thread thread2 = new Thread(() -> {
list.add("element2");
});
thread1.start();
thread2.start();
try {
thread1.join();
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
}
- 示例 - ConcurrentHashMap:
import java.util.concurrent.ConcurrentHashMap;
public class ConcurrentHashMapExample {
public static void main(String[] args) {
ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
Thread thread1 = new Thread(() -> {
map.put("key1", 1);
});
Thread thread2 = new Thread(() -> {
map.put("key2", 2);
});
thread1.start();
thread2.start();
try {
thread1.join();
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(map);
}
}
- 使用场景:
CopyOnWriteArrayList
适用于读多写少的场景,例如事件监听列表,多个线程可能频繁读取事件,但很少添加或删除监听器。
ConcurrentHashMap
适用于高并发读写的场景,如在大型的多线程Web应用程序中,需要频繁地读取和更新缓存数据的场景。