线程安全

关于java.util.Vector 或 java.util.Hashtable类过时的讨论

≡放荡痞女 提交于 2019-12-01 14:15:13
某些高级IDE在检测代码成熟问题时,会报告集合是否过时的问题。目前过时的集合类有两个java.util.Vector 和 java.util.Hashtable 。 Vector的api描述是:从jdk 1.2版本开始,该类被修正为实现List接口,并成为Java Collection集合框架的一员,区别于其他一些新的集合实现类,Vector是线程安全的。如果是一个线程安全的实现,推荐使用ArrayList代替Vector。 Hashtable的api描述是:从jdk 1.2版本开始,该类被修正为实现List接口,并成为Java Collection集合框架的一员,区别于其他一些新的集合实现类,Hashtable是线程安全的。如果是一个线程安全的实现,推荐使用HashMap代替Hashtable。如果是高并发的线程安全的实现,推荐使用ConcurrentHashMap代替Hashtable。 Vector和ArrayList区别 Vector和ArrayList Vector和ArrayList在使用上非常相似,都可用来表示一组数量可变的对象应用的集合,并且可以随机地访问其中的元素。 Vector的方法都是同步的(Synchronized),是线程安全的(thread-safe),而ArrayList的方法不是,由于线程的同步必然要影响性能,因此

线程安全好文章

霸气de小男生 提交于 2019-12-01 13:26:36
转:https://www.cnblogs.com/lixinjie/p/10817860.html 不是线程的安全 面试官问:“什么是线程安全”,如果你不能很好的回答,那就请往下看吧。 论语中有句话叫“学而优则仕”,相信很多人都觉得是“学习好了可以做官”。然而,这样理解却是错的。切记望文生义。 同理,“线程安全”也不是指线程的安全,而是指内存的安全。为什么如此说呢?这和操作系统有关。 目前主流操作系统都是多任务的,即多个进程同时运行。为了保证安全,每个进程只能访问分配给自己的内存空间,而不能访问别的进程的,这是由操作系统保障的。 在每个进程的内存空间中都会有一块特殊的公共区域,通常称为堆(内存)。进程内的所有线程都可以访问到该区域,这就是造成问题的潜在原因。 假设某个线程把数据处理到一半,觉得很累,就去休息了一会,回来准备接着处理,却发现数据已经被修改了,不是自己离开时的样子了。可能被其它线程修改了。 比如把你住的小区看作一个进程,小区里的道路/绿化等就属于公共区域。你拿1万块钱往地上一扔,就回家睡觉去了。睡醒后你打算去把它捡回来,发现钱已经不见了。可能被别人拿走了。 因为公共区域人来人往,你放的东西在没有看管措施时,一定是不安全的。内存中的情况亦然如此。 所以线程安全指的是,在堆内存中的数据由于可以被任何线程访问到,在没有限制的情况下存在被意外修改的风险。

五、原子操作(CAS)

删除回忆录丶 提交于 2019-12-01 13:21:06
原子操作(CAS) 一、CAS(Compare And Set) ​ Compare And Set(或Compare And Swap),CAS是解决多线程并行情况下使用锁造成性能损耗的一种机制,CAS操作包含三个操作数—— 内存位置 (V)、 预期原值 (A)、 新值 (B)。如果内存位置的值与预期原值相匹配,那么处理器会自动将该位置值更新为新值。否则,处理器不做任何操作。无论哪种情况,它都会在CAS指令之前返回该位置的值。CAS有效地说明了“我认为位置V应该包含值A;如果包含该值,则将B放到这个位置;否则,不要更改该位置,只告诉我这个位置现在的值即可。 ​ 在java中可以通过锁和循环CAS的方式来实现原子操作。Java中 java.util.concurrent.atomic包相关类就是 CAS的实现,atomic包里包括以下类: AtomicBoolean 可以用原子方式更新的 boolean 值。 AtomicInteger 可以用原子方式更新的 int 值。 AtomicIntegerArray 可以用原子方式更新其元素的 int 数组。 AtomicIntegerFieldUpdater 基于反射的实用工具,可以对指定类的指定 volatile int 字段进行原子更新。 AtomicLong 可以用原子方式更新的 long 值。 AtomicLongArray

Java容器总结

三世轮回 提交于 2019-12-01 13:06:49
容器总结 Java容器工具包框架图 List,Set,Map三者的区别 List(对付顺序的好帮手): List接口存储一组不唯一(可以有多个元素引用相同的对象),有序的对象 Set(注重独一无二的性质): 不允许重复的集合。不会有多个元素引用相同的对象。 Map(用Key来搜索的专家): 使用键值对存储。Map会维护与Key有关联的值。两个Key可以引用相同的对象,但Key不能重复,典型的Key是String类型,但也可以是任何对象。 Arraylist 与 LinkedList 区别 是否保证线程安全: ArrayList 和 LinkedList 都是不同步的,也就是不保证线程安全; 底层数据结构: Arraylist 底层使用的是 Object 数组;LinkedList 底层使用的是 双向链表 数据结构(JDK1.6之前为循环链表,JDK1.7取消了循环。注意双向链表和双向循环链表的区别,下面有介绍到!) 插入和删除是否受元素位置的影响: ① ArrayList 采用数组存储,所以插入和删除元素的时间复杂度受元素位置的影响。 比如:执行add(E e) 方法的时候, ArrayList 会默认在将指定的元素追加到此列表的末尾,这种情况时间复杂度就是O(1)。但是如果要在指定位置 i 插入和删除元素的话(add(int index, E element) )时间复杂度就为

Java、Android数据结构小节

橙三吉。 提交于 2019-12-01 12:53:20
Java 数据结构 List List 都有序; 线程不安全; 有长度; 内部持有 modCount 记录修改次数 ArrayList 默认长度为10、超出长度时进行扩容(0.5倍),最大长度 2 的 31 次方 -8, 超出会OOM; 特点: 查快删改慢 LinkedList 双向链表, 链表通过内部类 Node 对象实现; 增删快查找慢, 查询做了二分(下标前、后半部分)查询优化 List 承载的实体实现 Comparable、Comparator 接口可以让 List 实现快速排序 Collections.synchronizedList(list); 可以使 List 线程安全 new ArrayList(new String[]) 以及 List.toArray() 可以实现 List、 Array 互转 Arrays.asList() 返回的 List 是 Arrays 的内部类, 它未提供写操作, 所以是只读的 Map Map 共有特性 无序; 线程不安全; Hashtable 线程安全 (公开方法都加了 synchronized ) 不允许 null key 和 null value 默认容量为 11, 默认负载因子 0.75 当 size > 容量 * 负载因子 时, 容量会扩容到 2N +1 该类已被淘汰(注意不是废弃), 如果不需要线程安全可以使用

JAVA面试——容器

不羁的心 提交于 2019-12-01 12:26:46
1、Java的容器有哪些? Java容器分为Collection和Map两大类,其下又有很多子类,如下所示:   ●Collection     。List     。ArrayList     。LinkedList     。Vector       ■Stack     。Set     。HashSet       ■LinkedHashSet     。TreeSet    ●Map      。HashMap     。LinkedHashMap     。TreeMap     。ConcurrentHashMap     。Hashtable 2、Collection和Collections有什么区别?   1)Collection是一个集合接口,它提供了对集合对行基本操作的通用接口方法,所有集合都是它的子类,比如List、Set等。    2)Collections是一个包装类,包含了很多静态方法,不能被实例化,就像个工具类,比如提供的排序方法:Collections, sort(list)。 3、 Collection 和 Collections 有什么区别?   List、Set、Map的区别主要体现在两个方面:元素是否有序'是否允许元素重复。 三者之间的区别,如下表: 4、 HashMap 和 Hashtable 有什么区别?   •存储:HashMap运行

Java基础笔试练习(四)

谁说胖子不能爱 提交于 2019-12-01 11:40:41
1.编译Java Application 源程序文件将产生相应的字节码文件,这些字节码文件的扩展名为( )。 A.java B.class C.html D.exe 答案: B 解析: Java源程序的后缀名为“.java”,经过编译之后生成的字节码文件后缀名为“.class” 2. 问以下哪个说法是正确的?() A 派生出子类 B, B 派生出子类 C,并且在 java 源代码有如下声明: A a0=new A(); A a1=new B(); A a2=new C(); A.只有第一行能通过编译 B.第1、2行能通过编译,但第3行编译出错 C.第1、2、3行能通过编译,但第2、3行运行时出错 D.第1行,第2行和第3行的声明都是正确的 答案: D 解析: 这个题考了两个点: 继承的传递性。 多态,父类引用指向子类对象。 3.以下哪个接口的定义是正确的?( ) A.interface B{ void print() { } ;} B.interface B{ static void print() ;} C.abstract interface B extends A1, A2 //A1、A2为已定义的接口{ abstract void print(){ };} D.interface B{ void print();} 答案: D 解析: A

高并发Web服务的演变—节约系统内存和CPU

梦想的初衷 提交于 2019-12-01 11:12:24
#0 系列目录# 应用系统架构 大型网站技术架构的演进与设计 大型网站技术架构的实践 大型网站图片服务器架构的演进 大型网站架构的灵魂—性能 大型网站架构的缓存 亿级Web系统搭建—单机到分布式集群 高并发Web服务的演变—节约系统内存和CPU #1 越来越多的并发连接数# 现在的Web系统面对的并发连接数在近几年呈现指数增长,高并发成为了一种常态,给Web系统带来不小的挑战。以最简单粗暴的方式解决,就是增加Web系统的机器和升级硬件配置。虽然现在的硬件越来越便宜,但是一味地通过增加机器来解决并发量的增长,成本是非常高昂的。 结合技术优化方案,才是更有效的解决方法 。 并发连接数为什么呈指数增长?实际上,从这几年的用户基数上看,这个数量并没有出现指数增长,因此它并非主要原因。 主要原因,还是web变得更复杂,交互更丰富所导致的 。 ##1.1 页面元素增多,交互复杂## Web页面元素越来越多,更为丰富。更多的资源元素,意味着更多的下载请求。Web系统的交互越来越复杂,交互场景和次数也大幅增加。以“www.qq.com”的首页为例子,刷新一次,大概会有244个请求。并且,在页面打开完成之后,还会有一些定时的查询或者上报请求持续运作。 目前的Http请求, 为了减少反复的创建和销毁连接行为,通常都建立长连接(Connection keep-alive) 。一经建立

Java并发:线程安全与锁优化

时间秒杀一切 提交于 2019-12-01 11:07:08
概述 人们很难想象现实中的对象在一项工作进行期间,会被不停地中断和切换,对象的属性(数据)可能会在中断期间被修改和变“脏”,而这些事情在计算机世界中则是很正常的事情。有时候,良好的设计原则不得不向现实做出一些让步,我们必须让程序在计算机中正确无误地运行,然后再考虑如何将代码组织得更好,让程序运行更快。对于“高效并发”来说,首先需要保证并发的正确性,然后在此基础上实现高效。 1.线程安全 《Java Concurrency In Practice》的作者Brian Goetz对“线程安全”有一个比较恰当的定义:“当多个线程访问一个对象时,如果不用考虑这些线程在运行时环境下的调度和交替执行,也不需要进行额外的同步,或者在调用方进行任何其他的协调操作,调用这个对象的行为都可以获得正确的结果,那这个对象是线程安全的”。 这个定义比较严谨,它要求线程安全的代码都必须具备一个特征:代码本身封装了所有必要的正确性保障手段(如互斥同步等),令调用者无须关心多线程的问题,更无须自己采取任何措施来保证多线程的正确调用。这点听起来简单,但其实并不容易做到,在大多数场景中,我们都会将这个定义弱化一些,如果把“调用这个对象的行为”限定为“单次调用”,这个定义的其他描述也能够成立的话,我们就可以称它是线程安全了。 1.1 Java语言中的线程安全 按照线程安全的“安全程度”由强至弱来排序

从 volatile 说到 i++ 的线程安全问题

左心房为你撑大大i 提交于 2019-12-01 10:42:17
volatile关键字保证了在多线程环境下,被修饰的变量在别修改后会马上同步到主存,这样该线程对这个变量的修改就是对所有其他线程可见的,其他线程能够马上读到这个修改后值. Thread的本地内存 每个Thread都拥有自己的线程存储空间 Thread何时同步本地存储空间的数据到主存是不确定的 例子 借用Google JEREMY MANSON 的解释,上图表示两个线程并发执行,而且代码顺序上为Thread1->Thread2 1. 不用 volatile 假如ready字段不使用volatile,那么Thread 1对ready做出的修改对于Thread2来说未必是可见的,是否可见是不确定的.假如此时thread1 ready泄露了(leak through)了,那么Thread 2可以看见ready为true,但是有可能answer的改变并没有泄露,则thread2有可能会输出 0 (answer=42对thread2并不可见) 2. 使用 volatile 使用volatile以后,做了如下事情 每次修改volatile变量都会同步到主存中 每次读取volatile变量的值都强制从主存读取最新的值(强制JVM不可优化volatile变量,如JVM优化后变量读取会使用cpu缓存而不从主存中读取) 在Thread中对volatile变量的写操作之前的操作对别的Thread都是可见的