1.LinkedList源码分析

LinkedList的是基于链表实现的java集合类,通过index插入到指定位置的时候使用LinkedList效率要比ArrayList高,以下源码分析是基于JDK1.8.

1.1 类的继承结构

LinkedList类的继承结构如如下所示:

从以上继承结构图中可以看到,最顶层接口为Iterable接口,实现此接口的类支持通过迭代器遍历集合中的元素。其他相关接口如Collection、List、Queue、Deque分别为列表,队列功能的相关接口,即此LinkedList支持列表、队列的相关操作。Serializable接口为序列化标志接口,即所有需要序列化的类都需要实现此接口。

1.2 LinkedList数据结构说明

首先我们来看下LinkedList中保存数据的内部类定义源码如下:

private static class Node<E> {
E item;
Node<E> next;
Node<E> prev; Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}

通过以上定义可以看出来每个节点中除了保存元素的值之外还保存了前后节点的引用。即使用了链表的数据接口保存数据元素。数据结构如下图所示:

在LinkedList类中,只是定义了两个Node类型的属性,定义如下:

 transient Node<E> first;
transient Node<E> last;

这两个属性分别表示头节点和尾节点,始终指向链表的第一个节点和最后一个节点。

1.3 关键方法源码分析

当不指定index往LinkedList中添加元素的时候默认是在链表的尾部添加数据,源代码如下

  void linkLast(E e) {
//保存链表插入之前的最后一个节点
final Node<E> l = last;
//将新节点的preNode指向链表最后一个节点
final Node<E> newNode = new Node<>(l, e, null);
last指向插入后的尾节点
last = newNode;
if (l == null)
//当第一次插入数据的时候,头节点和尾节点指向同一个节点
first = newNode;
else
//插入之前的尾节点的nextNode指向新插入的节点
l.next = newNode;
size++;
modCount++;
}

插入节点的详细操作如上面代码注释。在次操作中其实last即尾节点是共享资源,当多个线程同时执行此方法的时候,其实会出现线程安全问题。具体的线程安全问题后面分析。

当指定index插入数据的时候,源代码如下所示:

public void add(int index, E element) {
checkPositionIndex(index); if (index == size)
linkLast(element);
else
linkBefore(element, node(index));
}

在指定index插入元素的时候会先查询出index位置的元素,然后调用linkBefore将此元素插入到查询到的元素的前一个位置。其中linkBefore源码如下所示:

void linkBefore(E e, Node<E> succ) {
// assert succ != null;
final Node<E> pred = succ.prev;
//新建节点,并将preNode指向idnex-1节点
final Node<E> newNode = new Node<>(pred, e, succ);
//插入前的index节点的prev指向新节点
succ.prev = newNode;
if (pred == null)
first = newNode;
else
//index-1节点的nextNode指向新节点
pred.next = newNode;
size++;
modCount++;
}

在指定节点插入的方式如上注释所示。此操作中共享资源是插入之前index节点。同样会出现并发安全问题,下面对此问题进行分析。

2.LinkedList并发插入时节点覆盖的问题

在指定index插入或者addLast的时候都是在链表的尾部插入数据,当并发插入的时候如果出现以下执行顺序的时候,会出现插入的数据被覆盖的问题。

当多个线程同时获取到相同的尾节点的时候,然后多个线程同时在此尾节点后面插入数据的时候会出现数据覆盖的问题。

LinkedList源码和并发问题分析的更多相关文章

  1. ArrayList 和 LinkedList 源码分析

    List 表示的就是线性表,是具有相同特性的数据元素的有限序列.它主要有两种存储结构,顺序存储和链式存储,分别对应着 ArrayList 和 LinkedList 的实现,接下来以 jdk7 代码为例 ...

  2. java集合系列之LinkedList源码分析

    java集合系列之LinkedList源码分析 LinkedList数据结构简介 LinkedList底层是通过双端双向链表实现的,其基本数据结构如下,每一个节点类为Node对象,每个Node节点包含 ...

  3. java基础解析系列(十)---ArrayList和LinkedList源码及使用分析

    java基础解析系列(十)---ArrayList和LinkedList源码及使用分析 目录 java基础解析系列(一)---String.StringBuffer.StringBuilder jav ...

  4. Android版数据结构与算法(三):基于链表的实现LinkedList源码彻底分析

    版权声明:本文出自汪磊的博客,未经作者允许禁止转载. LinkedList 是一个双向链表.它可以被当作堆栈.队列或双端队列进行操作.LinkedList相对于ArrayList来说,添加,删除元素效 ...

  5. LinkedList源码分析和实例应用

    1. LinkedList介绍 LinkedList是继承于AbstractSequentialList抽象类,它也可以被当作堆栈.队列或者双端队列使用. LinkedList实现了Deque接口,即 ...

  6. Java集合之LinkedList源码分析

    概述 LinkedLIst和ArrayLIst一样, 都实现了List接口, 但其内部的数据结构不同, LinkedList是基于链表实现的(从名字也能看出来), 随机访问效率要比ArrayList差 ...

  7. Java入门系列之集合LinkedList源码分析(九)

    前言 上一节我们手写实现了单链表和双链表,本节我们来看看源码是如何实现的并且对比手动实现有哪些可优化的地方. LinkedList源码分析 通过上一节我们对双链表原理的讲解,同时我们对照如下图也可知道 ...

  8. Java集合基于JDK1.8的LinkedList源码分析

    上篇我们分析了ArrayList的底层实现,知道了ArrayList底层是基于数组实现的,因此具有查找修改快而插入删除慢的特点.本篇介绍的LinkedList是List接口的另一种实现,它的底层是基于 ...

  9. 从面试角度分析LinkedList源码

    注:本系列文章中用到的jdk版本均为java8 LinkedList类图如下: LinkedList底层是由双向链表实现的.链表好比火车,每节车厢包含了车厢和连接下一节车厢的连接点.而双向链表的每个节 ...

随机推荐

  1. PV 动态供给 - 每天5分钟玩转 Docker 容器技术(153)

    前面的例子中,我们提前创建了 PV,然后通过 PVC 申请 PV 并在 Pod 中使用,这种方式叫做静态供给(Static Provision). 与之对应的是动态供给(Dynamical Provi ...

  2. 百度播放器SDK 播放MP4格式视频有声音无画面问题解决

    此处为记录解决过程. 所链接使用的MP4格式视频为codec id是mp4v-20.使用手机自带播放器可以播放,使用百度云媒体播放器不能无画面.经调试,Android Baidu-Cloud-Play ...

  3. idea的spring boot项目,运行时不要显示在dashboard中

    将对应项目的上图配置,取消勾选即可.

  4. ng-model,ng-value,ng-bind,{{}}----angularJS数据绑定

    最典型用法 双向绑定 <input type="text" value="{{apple}}" ng-model="apple" &g ...

  5. 学习linux的一些指令

    简单说一下我对linux的理解,linux只有一个根目录,所有目录都挂在该根目录上,磁盘进行分区,然后生成文件系统,挂到目录上,/etc/fstab用于记录系统配置,比如分区挂载点,开机自动挂载等等. ...

  6. Java 枚举类型简介

    目录 Java 枚举示例 Java 枚举构造函数 枚举类型是用于定义常量集合的特殊类型,更确切的说,JAVA枚举类型是一种特殊的 java 类.枚举类型可以包含常量.方法等.在 java5 中添加了 ...

  7. leetcode 283. Move Zeroes -easy

    题目链接:https://leetcode.com/problems/move-zeroes/ 题目内容: Given an array nums, write a function to move ...

  8. Java入门之JDK的安装和环境变量的配置

    Java的版本 1. Java SEjava se 以前称为J2SE.它允许开发和部署在桌面.服务器.嵌入式环境和实时环境中使用的 Java 应用程序.Java SE是基础包,但是也包含了支持 Jav ...

  9. [APIO 2016]Gap

    Description 题库链接 给你一个长度为 \(N\) 的单调递增序列 \(A\) .交互时允许你调用 MinMax(s, t, &mn, &mx) 函数,表示序列元素的值在 \ ...

  10. 计蒜客NOIP模拟赛(2) D1T1邻家男孩

    凡是一个具有领导力的孩子.现实生活中他特别喜欢玩一个叫做 UNO 的纸牌游戏,他也总是带着其他小朋友一起玩,然后战胜他们.慢慢地,他厌倦了胜利,于是准备发明一种新的双人纸牌游戏. 初始时,每个人手中都 ...