热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Java中的不可变集合与同步集合详解

本文将详细探讨Java中提供的不可变集合(如`Collections.unmodifiableXXX`)和同步集合(如`Collections.synchronizedXXX`)的实现原理及使用方法,帮助开发者更好地理解和应用这些工具。
在 Java 编程中,`Collections` 类提供了多种工具方法来创建不可变集合和同步集合。这两种集合类型在多线程环境和数据保护方面有着重要的应用。以下是它们的详细介绍。

### 一、不可变集合(Unmodifiable Collections)

#### 1. 实现原理
不可变集合通过包装一个已有的集合,并重写所有可能改变集合状态的方法来实现。如果尝试调用这些方法,将会抛出 `UnsupportedOperationException` 异常。以 `UnmodifiableList` 为例,其内部结构如下:

```java
static class UnmodifiableList extends UnmodifiableCollection implements List {
private static final long serialVersiOnUID= -283967356065247728L;
final List list;

UnmodifiableList(List list) {
super(list);
this.list = list;
}

public boolean equals(Object o) {
return o == this || list.equals(o);
}

public int hashCode() {
return list.hashCode();
}

public E get(int index) {
return list.get(index);
}

public E set(int index, E element) {
throw new UnsupportedOperationException();
}

public void add(int index, E element) {
throw new UnsupportedOperationException();
}

public E remove(int index) {
throw new UnsupportedOperationException();
}

// 其他方法省略...
}
```

`UnmodifiableList` 继承自 `UnmodifiableCollection`,后者已经重写了所有可能改变集合状态的方法,使其抛出 `UnsupportedOperationException`。`UnmodifiableList` 进一步实现了 `List` 接口,并针对列表特有的方法进行了相应的处理。

#### 2. 使用示例
创建一个不可变列表的示例如下:

```java
List list = new ArrayList<>();
list.add("aa");
list.add("bb");
List unmodifiableList = Collections.unmodifiableList(list);
System.out.println(unmodifiableList); // 输出 [aa, bb]
```

尝试向 `unmodifiableList` 添加元素会抛出 `UnsupportedOperationException` 异常。需要注意的是,`Collections.unmodifiableList` 创建的并不是真正的不可变集合,如果原始集合被修改,不可变集合的内容也会随之变化。

```java
list.add("cc");
System.out.println(unmodifiableList); // 输出 [aa, bb, cc]
```

### 二、同步集合(Synchronized Collections)

#### 1. 实现原理
同步集合通过在每个方法调用时添加同步锁来实现线程安全。以 `SynchronizedCollection` 为例,其内部结构如下:

```java
static class SynchronizedCollection implements Collection, Serializable {
private static final long serialVersiOnUID= 3053995032091335093L;
final Collection c; // 被包装的集合
final Object mutex; // 同步锁

SynchronizedCollection(Collection c) {
this.c = Objects.requireNonNull(c);
mutex = this;
}

SynchronizedCollection(Collection c, Object mutex) {
this.c = Objects.requireNonNull(c);
this.mutex = Objects.requireNonNull(mutex);
}

public int size() {
synchronized (mutex) {
return c.size();
}
}

public boolean isEmpty() {
synchronized (mutex) {
return c.isEmpty();
}
}

public boolean contains(Object o) {
synchronized (mutex) {
return c.contains(o);
}
}

// 其他方法省略...
}
```

`SynchronizedCollection` 在每个方法中使用 `synchronized` 关键字来确保线程安全。需要注意的是,某些方法(如 `iterator`)返回的迭代器本身并不是线程安全的,需要用户手动同步。

#### 2. 使用示例
创建一个同步列表的示例如下:

```java
List list = new ArrayList<>();
List synchrOnizedList= Collections.synchronizedList(list);
```

虽然 `Collections.synchronizedList` 提供了基本的线程安全,但在某些情况下,同步容器仍然可能遇到并发问题,例如在迭代过程中修改集合可能会导致 `ConcurrentModificationException` 异常。因此,在多线程环境中使用同步集合时,需要额外注意这些潜在的问题。
推荐阅读
author-avatar
从1前2有3个4人_706
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有