- 浏览: 356952 次
- 性别:
- 来自: 大连
最新评论
-
f756692193:
你好,这个问题解决了吗??我也遇到了。。当一个生产者,一个消费 ...
rabbitmq的几个小问题,被郁闷了 -
flashing:
jz20110918 写道目前已经有了多个证书的情况下需要考虑 ...
CentOS 7下面OpenVPN和OpenSSL的问题总结 -
flashing:
jz20110918 写道flashing 写道jz20110 ...
CentOS 7下面OpenVPN和OpenSSL的问题总结 -
jz20110918:
目前已经有了多个证书的情况下需要考虑兼容性,所以不知楼主有没有 ...
CentOS 7下面OpenVPN和OpenSSL的问题总结 -
jz20110918:
flashing 写道jz20110918 写道您好,我现在也 ...
CentOS 7下面OpenVPN和OpenSSL的问题总结
昨天又看人讨论这个问题,发个帖,为新手整理思路,正本清源。
很多人面试、被面试的时候都会被反复问到这个蛋疼的问题:Vector和ArrayList区别是什么?(同理StringBuffer & StringBuilder,Hashtable & HashMap,etc.)
我想很多人都会说出这个以讹传讹了好多年的标准答案:Vector是同步的,ArrayList不是。
其实最主要的核心差别是(抛开API层面的接口关系不讲),JDK1.4之前的这些类,API里面的public函数,都加了synchronized关键字,而JAVA5之后的ArrayList之类的结构,则取消了这个同步关键字限制。
取消是必然的,因为这个“同步”,现实在并发环境中起不到作用。
为了把问题简单一点,我们来看一个这样的结构。
public class MyList { private int length = 0; public synchronized int add(Object newElement) { //做添加的操作,blablabla length++; } public synchronized int size() { return this.length; } }
好的,现在有一个MyList的实例,myList,被某线程的两个实例并发访问,线程A和线程B。
我们看看如果该线程类的实例,线程A和B都执行这样代码:
public void run() { if (myList.size() == 0) { //BTW:ArrayList里面应该用isEmpty()代替 myList.add(new Element()); } }
让我们看看这个MyList类的代码是Thread Safe的吗?假设一个如下的执行顺序:
1.线程A执行myList.size(),这时候线程B也进入了myList.size(),但是只能等线程A的myList.size()执行完毕
2.线程A的myList.size()执行完毕,再没有执行add之前,线程B执行了myList.size()
3.线程A执行了add,无论如何,这时候线程B也要执行add了,因为都满足了myList.size() == 0
run()函数里面的逻辑并没有正确的被执行。
synchronized 加在非静态函数上,相当于instance作为锁,即等价于:
synchronized (this) { //code... }
这个锁的粒度非常不好,即难以保证类内部的成员变量在并发下保持一致(如果有多个成员变量的话),也没法保证外面调用者的宏观逻辑是正确的,反倒降低了整体性能。
所以在JAVA5之后,JAVA把这个事情扔给了程序员,数据结构只是作为基础代码存在。
更具体的说,很多朋友都知道StringBuilder性能比StringBuffer好不少,其实作为项目整体层面来说,锁和拷贝是降低性能的罪魁祸首,尤其对于性能要求很极端的项目,应该尽量减少不必要的锁和拷贝;当然sun是提供api的,就更不能加入这样的不必要的同步代码了。
开发当中,如果一定需要锁,可以为具体的要保护的无关系的成员变量单独分配锁,这样可以保证获得最大的性能。
其实JAVA5还提供了很多用于并发的数据结构,比如ConcurrentMap的putIfAbsent就在一个比较好的粒度上给简化了程序员的代码,不会犯前面这个反例的错误。
将来,如果在scala、F#等FP语言能够普及,程序员也许不必再考虑这么多的并发问题。
评论
vector是线程安全的,就如同一个房间,房门上有把锁,锁只有一个钥匙,当很多人想进房间,拿到那把能开锁的钥匙(姑且叫做A)才可以进入房间,而等到A退出房间并将钥匙随便给到在房门口等待的其他一人(姑且叫做B)的手上,B才可以进入房间,这样能保证房间里的资源在同一时间只被一个人占用。
arrayList不是线程安全的,就如同一个房门上没有锁的房间,因而所有的人都可以同时进入房间,房间里的资源在同一时间被多个人占用。这样在多线程中会出现问题。比如说那个资源是马桶,多个人进去抢那一个马桶势必大大出手形成竞争(race condition)。这样说不准没有一个人能正常如厕,所以arrayList在多线程里面用的话会很危险。
反过来看楼主的说法,楼主用多个线程来查看vector,然后再往vector里面添加数据。
if(vector.size() == 0){
Thread.sleep(100);
vector.add(new Element());
}
我故意加了个Thread.sleep();
这样会存在什么问题呢,多个线程都会看到vector的空间等于0,然后往vector里面添加元素。就如同多个人看到房间里面的马桶一次都没有用过,于是都想用第一次,然后他们该怎么做呢?排队拿钥匙进入房间用马桶。于是马桶被用了3次。
而如果在这里是arrayList会是什么情况呢?所有的人都进去用,有可能马桶只被用了1次(arrayList里面只存用一个元素)。那为什么明明3个人用过马桶,最后却只被用了一次呢,这个与试试矛盾啊,这就是因为房门没有锁,3个人有可能同时共用了一次马桶,这个与事实想违背,所以说arrayList是不安全的。
那么楼主说vector也是不安全的 因为上面的一段代码,这段代码就好比是房间(1)外面有一个更大的房间(2),房间(2)的房门没有锁,所以所有的人都可以进入房间(2)来看,这样房间(2)是不安全的,不安全的原因是楼主没把房间上锁,但是房间(2)不安全并不代表房间(1)不是安全的。
{
private int clkID;
public void setClockID(int id)
{
clkID = id;
}
}
在这里,setClockId不需要同步,也能保证线程安全。这是由于int的赋值操作是原子的。这并不多可以理解为Java本身对他提供了同步的默认支持。
官方说法如下:32位或者更少位数的赋值是原子的。
如果把上面的int改成long(64位)。那么setClockId就不再是原子操作。也线程不再安全。如果要保证,那么加上synchronized。
当然后来jdk里Java又提供了一个AtomicLong之类的对象,这些对象能提供原子操作。
其实在讨论Vector和ArrayList的时候,是不需要出现到关于原子操作的讨论的。
它们俩跟原子操作就没关系。
还没太懂,同步和线程安全是两个不同的概念...
多线程同时直接操作一个Vector,做add操作。不会有报错。
1000个add后,vector里就有1000个数据。
多线程同时直接操作一个ArrayList,做add操作。有可能报错,也有可能出现数据被重写掉。
1000个add后,vector里只有999个数据。或者执行期间有index异常。
Vecotr的所有方法都是线程安全的。ArrayList不是。
我不知道你哪儿不懂。
你错了。
我脑子里的线程安全定义就是标准定义。
在多线程和单线程下工作,Vector的所有API(同步的)能表现出一致的行为,而ArrayList的API不能。
嘿嘿,原子的肯定是线程安全的。
线程安全的不一定是原子的。
囧死了,我在说废话~~~~
你能举例说明吗。
我觉得你说的不对,你举出例子来我应该可以反驳你。
”原子的肯定是线程安全的“ 这句话就不用举例。
“线程安全的不一定是原子的”的例子:
String对象,Date对象,Integer, Double....
这些类貌似有一种叫法:不可变类
Vector按你的分类应该叫什么?原子or线程安全?
但你的说法跟haigui.chen关于原子的说法是不一样的。
不明白为什么可以说到一起。
haigui.chen说道:我觉得你应该说Vector所有的方法是“原子”的,我其实是没懂你脑子里面的“线程安全”怎么定义的..
这句话明显应该是错的吧。
嘿嘿,原子的肯定是线程安全的。
线程安全的不一定是原子的。
囧死了,我在说废话~~~~
你能举例说明吗。
我觉得你说的不对,你举出例子来我应该可以反驳你。
”原子的肯定是线程安全的“ 这句话就不用举例。
“线程安全的不一定是原子的”的例子:
String对象,Date对象,Integer, Double....
这些类貌似有一种叫法:不可变类
嘿嘿,原子的肯定是线程安全的。
线程安全的不一定是原子的。
囧死了,我在说废话~~~~
你能举例说明吗。
我觉得你说的不对,你举出例子来我应该可以反驳你。
http://en.wikipedia.org/wiki/Thread_safe
http://en.wikipedia.org/wiki/Atomicity_(programming)
if (!vector.contains(element))
vector.add(element);
这种存在race condition,同步,不安全
嘿嘿,原子的肯定是线程安全的。
线程安全的不一定是原子的。
囧死了,我在说废话~~~~
你可以说不是非要数据库才会有事务.....
不是非要hibernate才会有乐观锁
一个是制定的规范,一个是根据这个规范的一种实现?
嘿嘿,原子的肯定是线程安全的。
线程安全的不一定是原子的。
囧死了,我在说废话~~~~
你可以说不是非要数据库才会有事务.....
不是非要hibernate才会有乐观锁
嘿嘿,原子的肯定是线程安全的。
线程安全的不一定是原子的。
囧死了,我在说废话~~~~
还没太懂,同步和线程安全是两个不同的概念...
多线程同时直接操作一个Vector,做add操作。不会有报错。
1000个add后,vector里就有1000个数据。
多线程同时直接操作一个ArrayList,做add操作。有可能报错,也有可能出现数据被重写掉。
1000个add后,vector里只有999个数据。或者执行期间有index异常。
Vecotr的所有方法都是线程安全的。ArrayList不是。
我不知道你哪儿不懂。
我觉得你没有真的理解线程安全。
可能是,在put if absent 下面,vector还会是线程安全的么?
vector本身是线程安全的,放在哪都是。
但vector本身的线程安全不能保证你使用了vector的应用程序是线程安全的。
懂了吗?
还没太懂,同步和线程安全是两个不同的概念...
多线程同时直接操作一个Vector,做add操作。不会有报错。
1000个add后,vector里就有1000个数据。
多线程同时直接操作一个ArrayList,做add操作。有可能报错,也有可能出现数据被重写掉。
1000个add后,vector里可能只有999个数据。或者执行期间有index异常。
Vecotr的所有方法都是线程安全的。ArrayList不是。
我不知道你哪儿不懂。
我理解的线程概念:
如果某个个类的一个对象,对于能够修改这个对象状态(如add)或者调用其他方法会影响其结果(如get)的任何方法,多线程调用任一方法时,能够保证任意时刻仅有一个线程能执行,
那么这个类就是线程安全的类。
怎么看你这句话都是错的,单CPU有真正意义上的线程"并发"吗?
不明白你说的意思。什么叫真正意义上的线程"并发"?
难道你认为N个CPU下同时运行N个线程才叫并发?这种情况我理解为并行。
我觉得你没有真的理解线程安全。
可能是,在put if absent 下面,vector还会是线程安全的么?
vector本身是线程安全的,放在哪都是。
但vector本身的线程安全不能保证你使用了vector的应用程序是线程安全的。
懂了吗?
还没太懂,同步和线程安全是两个不同的概念...
发表评论
-
秀一个神器IDEA的诡异BUG
2015-09-04 21:07 637话说我仍然是什么软件都能玩脱的选手... IDEA 14. ... -
Java语言的进化远远不够
2015-09-04 19:34 644最近用spring-boot做了一个项目,和grails相比 ... -
转载的:数字签名是什么?
2015-06-14 18:59 638http://www.ruanyifeng.com/blo ... -
研究了两个Console进度条和进度提示的小技巧
2015-05-02 21:32 761今天用maven下载项目的时候,突然发现这么多年以来我竟然 ... -
Grails 2.5.0/2.4.5 升级历险记 & JAVA7/8的一个小bug
2015-03-27 12:12 2647因为手头一个grails项目的性能有点问题,打算大幅度调整 ... -
如何快速生成pdf文件
2014-12-17 08:10 14如果要生成pdf文件,java里面itext当仁不让是首选。不 ... -
如何快速生成pdf文件
2014-12-17 08:10 703如果要生成pdf文件,java里面itext当仁不让是首选。不 ... -
通用池:commons pool 2
2014-05-28 13:51 20775首先感谢下文作者,虽然没看你的内容,但是参考了参数。 A ... -
Grails dirty check失败导致不发送update sql
2013-11-22 10:13 965更新: 经过@meltingsnower的提示,发现se ... -
JAVA3D 看来只能运行在桌面
2012-11-22 10:50 1561最近一个项目用Java3D写了个分析3D模型的组件,用于3D打 ... -
Spring,随想
2012-02-22 20:57 1148春天来了,正好在从新看springframework 3.1。 ... -
Guava的一个介绍文档
2010-12-27 20:49 1305看了感觉相当不错,一直都知道google Guava这玩意很好 ... -
spring security 3.0的控制一个帐号只允许一次登录
2010-11-25 08:19 13897spring security 3.0里面明确的说明了: se ... -
使用javassist处理字节码混淆过的class文件
2010-09-14 21:05 2316java程序员,有时候为了某种特定目的比如调试或者增强代码,不 ... -
grails开发最好的工具大概是spring sts了,更新
2010-05-30 13:53 1306http://www.grails.org/STS+Integ ... -
swingx的jdic的浏览器控件的混用awt和swing的z-order的bug
2010-03-27 15:15 1131这两个帖子应该可以解决之,mark一下。 http:/ ... -
ORACLE记录所有的SQL
2009-10-28 08:54 1044在$ORACLE_HOME/rdbms/admin/下 需要打 ... -
java -D如何一次性加入多个jar
2009-10-08 12:55 1428java -Djava.ext.dirs=lib YourMa ...
相关推荐
在C++编程中,`ArrayList`是一个常见的动态数组容器,其设计灵感来源于Java中的ArrayList类。这个类的主要目的是提供一个类似数组的...但在教学或研究场景中,自定义实现ArrayList可以帮助开发者更好地掌握C++的本质。
Vector、ArrayList都是以数组的形式存储在内存中,所以查询效率高,新增和删除效率不高,Vector被Synchronized修饰,所以线程是安全的,ArrayList线程不安全。LinkedList则以链表的形式进行存储,所以查询效率底,...
1. Vector和ArrayList的区别: - Vector是同步的,适用于线程安全的环境,但因为同步的实现会导致性能损耗。 - Vector在扩容时将容量翻倍,而ArrayList的扩容方式是增加约1.5倍的容量,这使得ArrayList在节约内存...
59、ArrayList和Vector的区别 44 60、HashMap和Hashtable的区别 44 61、List 和 Map 区别? 45 62、List, Set, Map是否继承自Collection接口? 45 63、List、Map、Set三个接口,存取元素时,各有什么特点? 45 64、说...
59、ArrayList和Vector的区别 44 60、HashMap和Hashtable的区别 44 61、List 和 Map 区别? 45 62、List, Set, Map是否继承自Collection接口? 45 63、List、Map、Set三个接口,存取元素时,各有什么特点? 45 64、说...
59、ArrayList和Vector的区别 44 60、HashMap和Hashtable的区别 44 61、List 和 Map 区别? 45 62、List, Set, Map是否继承自Collection接口? 45 63、List、Map、Set三个接口,存取元素时,各有什么特点? 45 64、说...
59、ArrayList和Vector的区别 44 60、HashMap和Hashtable的区别 44 61、List 和 Map 区别? 45 62、List, Set, Map是否继承自Collection接口? 45 63、List、Map、Set三个接口,存取元素时,各有什么特点? 45 64、说...
59、ArrayList和Vector的区别 44 60、HashMap和Hashtable的区别 44 61、List 和 Map 区别? 45 62、List, Set, Map是否继承自Collection接口? 45 63、List、Map、Set三个接口,存取元素时,各有什么特点? 45 64...
59、ArrayList和Vector的区别 47 60、HashMap和Hashtable的区别 48 61、List 和 Map 区别? 49 62、List, Set, Map是否继承自Collection接口? 49 63、List、Map、Set三个接口,存取元素时,各有什么特点? 49 64、说...
59、ArrayList和Vector的区别 44 60、HashMap和Hashtable的区别 44 61、List 和 Map 区别? 45 62、List, Set, Map是否继承自Collection接口? 45 63、List、Map、Set三个接口,存取元素时,各有什么特点? 45 64、说...
1. **存储方式**:ArrayList本质上是一个数组,元素存储在连续的内存位置,查询速度较快。 2. **动态扩展**:随着元素的增加,ArrayList会自动扩展其容量。 3. **遍历方式**:支持普通for循环、Iterator迭代器和增强...
4. 说出ArrayList,Vector,LinkedList的存储性能和特性 8 5. EJB是基于哪些技术实现的?并说出SessionBean和EntityBean的区别,StatefulBean和StatelessBean的区别。 9 6. Collection 和 Collections的区别。 9 7. &...
ArrayList本质上是动态数组,查询速度快,但插入和删除慢,且线程不安全。LinkedList作为链表实现,查询慢但增删快,同样线程不安全。而Vector是ArrayList的线程安全版本,但其性能较差,因为在多线程环境下,同步...
int和Integer有什么区别?** - `int`是基本数据类型,`Integer`是`int`的包装类。 - `int`只能表示整数值,而`Integer`可以表示`null`。 - 在自动装箱和拆箱的情况下,两者可以互相转换。 **4. String和...
ArrayList本质上是一个动态数组,它允许所有元素,包括null。添加、获取和设置元素的操作具有常量时间复杂度。但是,添加元素的效率为分摊的常数,添加n个元素需要O(n)的时间。ArrayList也是非同步的,需要同步时可...
3. int是原始类型,Integer是int的封装类,两者在内存管理和操作上有本质区别。原始类型直接存储值,而封装类存储的是对象引用,具有更多的方法和特性。默认值int是0,Integer是null。 4. String是不可变的,一旦...
ArrayList、LinkedList和Vector都是List接口的实现,它们之间的差异在于数据结构和性能:ArrayList适合随机访问,LinkedList适合顺序访问和频繁插入删除,Vector线程安全但效率较低。HashSet和TreeSet是Set接口的...
ArrayList和Vector基于数组实现,适合随机访问,但Vector同步方法使其性能较ArrayList低。LinkedList基于双向链表实现,适合频繁插入和删除,但在查找元素时需要遍历,因此效率较低。 多线程编程是Java面试的重点。...
Vector是List集合的另一种类型,其底层实现与ArrayList类似,它们之间的根本区别是ArrayList没有实现线程同步,而Vector则是实现了线程的同步加锁,其在并发的状态下线程是安全的,但在执行的效率上却不如ArrayList...
Java集合框架中的ArrayList、Vector和LinkedList都是List接口的实现,但它们的存储性能和特性有所不同。ArrayList和Vector都是基于动态数组实现的,它们的查找效率较高,但在添加或删除元素时需要移动数组元素,性能...