`
22cgreen
  • 浏览: 55212 次
  • 性别: Icon_minigender_2
  • 来自: 广州
社区版块
存档分类
最新评论

关于数据LinkedList的removefirst出错

阅读更多
我有一段这样的代码:

Java codeprivate LinkedList<Connection> freeCon = new LinkedList<Connection>();
public  Connection getConn()
{
Connection re = null;
if(freeCon.size()>0)
{
try {
re = freeCon.getFirst();
freeCon.removeFirst();
if(re.isClosed())
{
this.getConn();
}
} catch (SQLException e) {
e.printStackTrace();
} catch(NoSuchElementException e)
{
System.out.println("freeCon size:"+freeCon.size());
for(int i=0;i<freeCon.size();i++)
{
if(freeCon.get(i)==null)
{
System.out.println("freeCon.get("+i+")is Null");
}else{
System.out.println("Item is:"+freeCon.get(i).toString());
}
}
}
}else{
re = this.getConnByDateSource();
}
return re;
}

此代码有时会出现java.util.NoSuchElementException
java.util.LinkedList.remove(Unknown Source)
java.util.LinkedList.removeFirst(Unknown Source)
dlp.oa.sql.SqlOracle.getConn(SqlOracle.java:117)
这个异常不常发生,一般好几天发生一次,让我感到很奇怪的就是,re = freeCon.getFirst();没有出现NoSuchElementException为什么freeCon.remov
eFirst();会发生异常呢.看那个高手能道出个原因出来.

此错误重启tomcat就好了.

---------------------------------------------------------------------------------------------------------------
在我后期打的测试代码中发现,freeCon.size()输出结果为4,但freeCon.get(0)出现异常,同时在输入结果中连续出现多个
freeCon size:4字样,而且出现这种情况是因为异步发送邮件写日志的过程中,从记录的异常分析,因为异步的原因,发送邮件的线程
在一个时间里同时调用了这个方法再出现LinkedList出错的.

在没有同步的情况下.
LinkedList 出现size=4,但实际上LinkedList中没有任何元素的现象.

按常理来说,不管同步和异步,一个数的状态最后只有一种状态,为什么会使得size大小和实际元素不对呢.
我们从LinkedList源码来分析一下为什么会出现这种现象.
看一下size怎么来的.
public int size() {
return size;
    }
   
    可以看出是返回LinkedList的一个int类型的size属性,不过从这里可以看出LinkedList最大元素个数不能超过int类型的最大允许范围.
    其实上面一个方法的关键大于freeCon.removeFirst(),
    而re = freeCon.getFirst();只是读取元素,并不会对元素个数和实际个数不同步产生影响,我们来看看freeCon.removeFirst()
    -------------------------------------------------------------------------------------------
     public E removeFirst() {
return remove(header.next);
    }
    ---------------------------------------------------------------------------------------------
     private E remove(Entry<E> e) {
if (e == header)
    throw new NoSuchElementException();

        E result = e.element;
e.previous.next = e.next;
e.next.previous = e.previous;
        e.next = e.previous = null;
        e.element = null;
size--;
modCount++;
        return result;
    }
   
    这里有个疑问就是,不管有多少个线程同时操作这个方法,这里测试过,当一个线程出现异常并不会影响其它线的中断(其它没有异常的线程一样继续执行),
    因此就算10个线程同时调用这个方法,按理size最终应减少10次啊。最少不会size=4,元素就为空了,最少减少一个元素
    我就size减一,不管先后顺序最后结果都是-10,元素应对应size大小啊,最多size等于负数。也不存在size大于元素的情况。
   
    这里看来唯一出现问题的就是这段了。
   
     E result = e.element;
e.previous.next = e.next;
e.next.previous = e.previous;
        e.next = e.previous = null;
        e.element = null;
       
        我们想一下这时有一个线程执行到第4行代码,而别一个线程刚好执行到了第二行代码,这时会出现
        e.next = null, e.previous = null,为因第4行代码的原因,使得e发现了变化,但是另一线程并不知道e发生了变化
        他还当作原来的e在使用。
       
        我们再详细的说明一下:
        E result = e.element; element是一个对象的引用,对应于对象A吧。这里就是A的引用给了result
        e.previous.next = e.next; 把e的下一个引用作为e的上一引用中的下一个引用。也就是说
        e的下一个元素是e的上一个元素的下一个素,从而可以知自己被被排除了,就像1,2,3 这时2的上一个元素1,下一个元素3,
        这时有人说1的下一个元素是3,这时我们就成了1,3,当然只是说1的下一元素为3,那么虽然不能通过1找到2,但是可以通过
        3的上元素来找到2。因此就有了下面一行语句。
        e.next.previous = e.previous; 相当于说3的上一个元互为1。这时就元素从上元素及下一个元素来得到2了。
       
        e.next = e.previous = null; 这条语句就是把对象置null,使其能被垃圾回收器回收。
       
        e.element = null; 也是把其置null,给垃圾回收器回收,其实它的引用早传给了E result
       
        多线程一般只是发生计算时不按顺序执行的问题,一般不会出现数据不对的问题,如:我多个线程对i加1,不管谁先加1,但
        可以确定最后的结果,有多少个线程加1,就加了多少次,4个线程同时操作就是+4,一般不会出现数字结果无法预知的
        问题,而上面的问题关键是这种写法会在多线程同时访问中会出问题。
1
0
分享到:
评论

相关推荐

    使用LinkedList模拟堆栈

    本文将详细讲解如何使用Java中的LinkedList类来模拟这两种数据结构,并实现其基本操作。 堆栈(Stack)是一种后进先出(LIFO, Last In First Out)的数据结构,它遵循“先进后出”的原则。常见的堆栈操作有压栈...

    JAVA利用LinkedList构造栈与队列

    LinkedList不仅可以作为列表使用,还可以被巧妙地利用来构建栈(Stack)和队列(Queue)这两种基本数据结构。在本篇内容中,我们将探讨如何通过LinkedList实现栈和队列,以及它们在实际编程中的应用。 首先,栈是一...

    创建一个 LinkedList项目.docx

    LinkedList 是 Java 中的一种数据结构,属于线性数据结构的一种,但它与数组有着本质的不同。数组在内存中存储元素是连续的,而 LinkedList 则通过节点之间的引用相互连接,每个节点包含元素本身、指向前一个节点的...

    关于arraylist和linkedList的区别

    ### 关于ArrayList与LinkedList的区别 在Java编程语言中,`ArrayList`与`LinkedList`都是`List`接口的具体实现类,用于存储元素集合。虽然它们都实现了同样的接口并且提供了相同的基本功能,但在内部实现机制、性能...

    java中LinkedList集合类实现栈和队列.doc

    在Java编程语言中,LinkedList集合类是一个非常重要的数据结构,它可以用来实现栈和队列这两种特殊的数据结构。LinkedList是一个双链表,每个节点包含数据元素和两个引用,分别指向前后节点,这使得在列表中进行插入...

    用LinkedList实现队列和栈

    本篇文章将探讨如何利用`LinkedList`来实现队列和栈这两种数据结构,以及其背后的原理和源码分析。 ### 1. 队列(Queue) 队列是一种先进先出(FIFO, First In First Out)的数据结构。在Java中,可以使用`...

    ArrayList LinkedList Vector区别

    ArrayList、LinkedList、Vector 是 Java 中常用的数据结构实现类,它们都实现了 List 接口,但它们在存储方式、性能、线程安全性等方面有着不同特点。 首先,ArrayList 和 Vector 都是采用数组方式存储数据的,这种...

    List-LinkedList 单链表就地反转

    ### List-LinkedList 单链表就地反转 #### 概述 本文主要介绍单链表的就地反转算法实现,并通过具体的C语言代码示例来解释这一过程。单链表是一种常见的线性数据结构,其中每个元素包含一个指向下一个元素的指针。...

    LinkedList的实现.zip

    LinkedList是计算机科学中的一种基本数据结构,特别是在C++编程中,它被广泛用于处理动态集合。LinkedList的主要特点是每个元素(称为节点)包含数据以及指向下一个节点的指针,这种结构使得在列表中间添加或删除...

    java LinkedList的添加删除操作

    在提供的JiHe6.java源代码中,可能包含了关于LinkedList添加删除操作的示例实现,通过阅读和理解代码,可以进一步加深对LinkedList的理解。而Java.jpg文件可能是与这个主题相关的辅助图表或类图,帮助视觉上理解...

    Java 中Linkedlist类的源代码

    这个数据结构允许我们在列表的任何位置进行插入和删除操作,具有O(1)的时间复杂度,这使得LinkedList在需要频繁进行这些操作时比ArrayList更高效。LinkedList类位于java.util包中,它还实现了Deque(双端队列)接口...

    ArrayList和Linkedlist1

    在IT领域,特别是Java编程中,ArrayList和LinkedList是两种非常重要的数据结构,它们都是List接口的实现类。理解这两者的区别对于优化程序性能至关重要。面试官询问这些知识点,旨在评估应聘者的理论基础和实践能力...

    Arraylist与LinkedList区别

    1,ArrayList是数组的数据结构,LinkedList是链表的数据结构。 2,随机访问的时候,ArrayList的效率比较高,因为LinkedList要移动指针,而ArrayList是基于 3,索引(index)的数据结构,可以直接映射到。 4,插入、...

    LinkedList实践代码

    LinkedList是Java编程语言中的一种重要数据结构,它属于集合框架的一部分,主要用来存储有序的元素序列。LinkedList在实现上是一个双链表,每个节点(Node)包含数据元素和两个引用,一个指向前一个节点,另一个指向...

    从底层数据结构和CPU缓存两方面剖析LinkedList的查询效率为什么比ArrayList低.docx

    本文对比了 LinkedList 和 ArrayList 的查询效率,从底层数据结构和 CPU 缓存两个方面进行了分析。首先,从底层数据结构方面,ArrayList 的查询效率高于 LinkedList,因为 ArrayList 底层数据结构是动态数组,可以...

    LinkedList实现栈

    return stack.removeFirst(); } } ``` 2. 使用`java.util.concurrent`包:Java并发库提供了更高级的同步机制,如`BlockingQueue`。我们可以将LinkedList作为`BlockingQueue`的实现,利用其内置的线程安全特性。...

    LinkedList.zip

    在Java中,`java.util.LinkedList`类是链表数据结构的一个实现,它同时实现了`List`和`Deque`接口,支持双向遍历。 这个工程包含的Java文件可能涵盖了以下链表操作和概念: 1. **初始化链表**:创建一个空的链表,...

    java中LinkedList任意排序实例

    在Java编程中,LinkedList是一个非常重要的数据结构,它实现了List接口,允许我们在列表的任何位置进行插入和删除操作。LinkedList内部使用双向链表实现,因此它的遍历速度比ArrayList快,但随机访问性能较差。本...

    ArrayList LinkedList Vector性能测试

    LinkedList是基于双向链表实现的列表,每个节点包含数据和两个引用,分别指向前后节点。LinkedList在插入和删除操作时具有优势,因为它只需要改变相邻节点的引用即可,而无需移动元素。然而,对于随机读取,...

Global site tag (gtag.js) - Google Analytics