List小总结

如果你不相信努力和时光,那么成果就会是第一个选择辜负你的。不要去否定你自己的过去,也不要用你的过去牵扯你现在的努力和对未来的展望。不是因为拥有希望你才去努力,而是去努力了,你才有可能看到希望的光芒。List小总结,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

【arrayList和LinkedList区别】

arrayList底层是用数组实现的顺序表,是随机存取类型,可自动扩增,并且在初始化时,数组的长度是0,只有在增加元素时,长度才会增加。默认是10,不能无限扩增,有上限,在查询操作的时候性
能更好
LinkedList底层是用链表来实现的,是一个双向链表,注意这里不是双向循环链表,顺序存取类型。在源码中,似乎没有元素个数的限制。应该能无限增加下去,直到内存满了在进行删除,增加操作时性
能更好。 两个都是线程不安全的,在iterator时,会发生fail-fast:快速失效。

【arrayList和Vector的区别】

arrayList线程不安全,在用iterator,会发生fail-fast
Vector线程安全,因为在方法前加了Synchronized关键字。也会发生fail-fast

【fail-fast和fail-safe区别和什么情况下会发生】

简单的来说:在java.util下的集合都是发生fail-fast,而在java.util.concurrent下的发生的都是fail- safe。

1)fail-fast

快速失败,例如在arrayList中使用迭代器遍历时,有另外的线程对arrayList的存储数组进行了改变,比
如add、delete、等使之发生了结构上的改变,所以Iterator就会快速报一个java.util.ConcurrentModificationException
异常(并发修改异常),这就是快速失败。

2)fail-safe

安全失败,在java.util.concurrent下的类,都是线程安全的类,他们在迭代的过程中,如果有线程进行
结构的改变,不会报异常,而是正常遍历,这就是安全失败

3)为什么在java.util.concurrent包下对集合有结构的改变,却不会报异常?

在concurrent下的集合类增加元素的时候使用Arrays.copyOf()来拷贝副本,在副本上增加元素,如果有 其他线程在此改变了集合的结构,那也是在副本上的改变,而不是影响到原集合,迭代器还是照常遍
历,遍历完之后,改变原引用指向副本,所以总的一句话就是如果在此包下的类进行增加删除,就会出现一个副本。所以能防止fail-fast,这种机制并不会出错,所以我们叫这种现象为fail-safe。

4)vector也是线程安全的,为什么是fail-fast呢?

这里搞清楚一个问题,并不是说线程安全的集合就不会报fail-fast,而是报fail-safe,你得搞清楚前面所
说答案的原理,出现fail-safe是因为他们在实现增删的底层机制不一样,就像上面说的,会有一个副本,而像arrayList、linekdList、verctor等,他们底层就是对着真正的引用进行操作,所以才会发生异 常。

5)既然是线程安全的,为什么在迭代的时候,还会有别的线程来改变其集合的结构呢(也就是对其 删除和增加等操作)?

首先,我们迭代的时候,根本就没用到集合中的删除、增加,查询的操作,就拿vector来说,我们都没有用那些加锁的方法,也就是方法锁放在那没人拿,在迭代的过程中,有人拿了那把锁,我们也没有办法,因为那把锁就放在那边。

【举例说明fail-fast和fail-safe的区别】
1.fail-fast
在这里插入图片描述
1.fail-safe
通过CopyOnWriteArrayList这个类来做实验,不用管这个类的作用,但是他确实没有报异常, 并且还通过第二次打印,来验证了上面我们说创建了副本的事情。
原理是在添加操作时会创建副本,在副本上进行添加操作,等迭代器遍历结束后,会将原引用 改为副本引用,所以我们在创建了一个list的迭代器,结果打印的就是123444了,
证明了确实改变成为了副本引用,后面为什么是三个4,原因是我们循环了3次,不久添加了3 个4吗。看下add的源码。
[
在这里插入图片描述

【为什么现在都不提倡使用vector了】

1)vector实现线程安全的方法是在每个操作方法上加锁,这些锁并不是必须要的,在实际开发中,
一般都是通过锁一系列的操作来实现线程安全,也就是说将需要同步的资源放一起加锁来保证线程安 全。
2)如果多个Thread并发执行一个已经加锁的方法,但是在该方法中,又有vector的存在,vector
本身实现中已经加锁了,那么相当于锁上又加锁,会造成额外的开销。
3)就如上面第三个问题所说的,vector还有fail-fast的问题,也就是说它也无法保证遍历安全,在
遍历时又得额外加锁,又是额外的开销,还不如直接用arrayList,然后再加锁呢。

总结:Vector在你不需要进行线程安全的时候也会给你加锁,也就导致了额外开销,所以在jdk1.5之后就被弃用了,现在如果要用到线程安全的集合,都是从java.util.concurrent包下去拿相应的类。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/198014.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!