热门标签 | 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` 异常。因此,在多线程环境中使用同步集合时,需要额外注意这些潜在的问题。
推荐阅读
  • Scala 实现 UTF-8 编码属性文件读取与克隆
    本文介绍如何使用 Scala 以 UTF-8 编码方式读取属性文件,并实现属性文件的克隆功能。通过这种方式,可以确保配置文件在多线程环境下的一致性和高效性。 ... [详细]
  • 从 .NET 转 Java 的自学之路:IO 流基础篇
    本文详细介绍了 Java 中的 IO 流,包括字节流和字符流的基本概念及其操作方式。探讨了如何处理不同类型的文件数据,并结合编码机制确保字符数据的正确读写。同时,文中还涵盖了装饰设计模式的应用,以及多种常见的 IO 操作实例。 ... [详细]
  • 深入解析Java枚举及其高级特性
    本文详细介绍了Java枚举的概念、语法、使用规则和应用场景,并探讨了其在实际编程中的高级应用。所有相关内容已收录于GitHub仓库[JavaLearningmanual](https://github.com/Ziphtracks/JavaLearningmanual),欢迎Star并持续关注。 ... [详细]
  • 本文详细记录了在基于Debian的Deepin 20操作系统上安装MySQL 5.7的具体步骤,包括软件包的选择、依赖项的处理及远程访问权限的配置。 ... [详细]
  • 本文详细介绍了 Dockerfile 的编写方法及其在网络配置中的应用,涵盖基础指令、镜像构建与发布流程,并深入探讨了 Docker 的默认网络、容器互联及自定义网络的实现。 ... [详细]
  • 数据库内核开发入门 | 搭建研发环境的初步指南
    本课程将带你从零开始,逐步掌握数据库内核开发的基础知识和实践技能,重点介绍如何搭建OceanBase的开发环境。 ... [详细]
  • 深入解析Spring Cloud Ribbon负载均衡机制
    本文详细介绍了Spring Cloud中的Ribbon组件如何实现服务调用的负载均衡。通过分析其工作原理、源码结构及配置方式,帮助读者理解Ribbon在分布式系统中的重要作用。 ... [详细]
  • 本文探讨了如何优化和正确配置Kafka Streams应用程序以确保准确的状态存储查询。通过调整配置参数和代码逻辑,可以有效解决数据不一致的问题。 ... [详细]
  • 深入解析 Apache Shiro 安全框架架构
    本文详细介绍了 Apache Shiro,一个强大且灵活的开源安全框架。Shiro 专注于简化身份验证、授权、会话管理和加密等复杂的安全操作,使开发者能够更轻松地保护应用程序。其核心目标是提供易于使用和理解的API,同时确保高度的安全性和灵活性。 ... [详细]
  • 在 Flutter 开发过程中,开发者经常会遇到 Widget 构造函数中的可选参数 Key。对于初学者来说,理解 Key 的作用和使用场景可能是一个挑战。本文将详细探讨 Key 的概念及其应用场景,并通过实例帮助你更好地掌握这一重要工具。 ... [详细]
  • 深入理解Redis的数据结构与对象系统
    本文详细探讨了Redis中的数据结构和对象系统的实现,包括字符串、列表、集合、哈希表和有序集合等五种核心对象类型,以及它们所使用的底层数据结构。通过分析源码和相关文献,帮助读者更好地理解Redis的设计原理。 ... [详细]
  • 不确定性|放入_华为机试题 HJ9提取不重复的整数
    不确定性|放入_华为机试题 HJ9提取不重复的整数 ... [详细]
  • 对象自省自省在计算机编程领域里,是指在运行时判断一个对象的类型和能力。dir能够返回一个列表,列举了一个对象所拥有的属性和方法。my_list[ ... [详细]
  • 本文详细解析了Java中hashCode()和equals()方法的实现原理及其在哈希表结构中的应用,探讨了两者之间的关系及其实现时需要注意的问题。 ... [详细]
  • 本文详细介绍了如何使用 Yii2 的 GridView 组件在列表页面实现数据的直接编辑功能。通过具体的代码示例和步骤,帮助开发者快速掌握这一实用技巧。 ... [详细]
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社区 版权所有