关于数据LinkedList的removefirst出错
2009-09-03 18:33
183 查看
关于数据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,一般不会出现数字结果无法预知的
问题,而上面的问题关键是这种写法会在多线程同时访问中会出问题。
相关文章推荐
- Java系列: 关于LinkedList的 ListIterator的add和remove
- 关于ArrayList与LinkedList添加数据的效率问题
- 关于java列表数据类型(ArrayList, LinkedList)的add与get
- JavaSE8基础 LinkedList<String> removeFirst removeLast 移除首尾元素
- 数据结构之Remove Linked List Elements 以及二叉树对称Symmetric Tree
- LeetCode OJ :Remove Linked List Elements (移除链表元素)
- 关于android SDK安装Failed to fetch URL http://dl-ssl.google.com/android/repository/addons_list-1.xml出错
- 【leetcode】Remove Linked List Elements
- 重拾编程之路--jeetcode(java)--Remove Linked List Elements
- 203. Remove Linked List Elements
- 关于LinkedList的三种写法的效率
- Remove Linked List Elements
- 关于MySQL数据库数据通过.sql文件导入数据出错的问题
- 203. Remove Linked List Elements
- list 集合如何remove重复数据
- [LeetCode]Remove Linked List Elements
- [LeetCode]203 Remove Linked List Elements
- 2.ArrayList LinkedList之remove
- 关于DateList一行绑定多个数据分页(一)cs文件
- 203. Remove Linked List Elements Leetcode Python