线程安全

并发队列ConcurrentLinkedQueue和阻塞队列LinkedBlockingQueue用

岁酱吖の 提交于 2019-12-03 16:14:53
在Java多线程应用中,队列的使用率很高,多数生产消费模型的首选数据结构就是队列。Java提供的线程安全的Queue可以分为阻塞队列和非阻塞队列,其中阻塞队列的典型例子是BlockingQueue,非阻塞队列的典型例子是ConcurrentLinkedQueue,在实际应用中要根据实际需要选用阻塞队列或者非阻塞队列。 注:什么叫线程安全?这个首先要明确。线程安全就是说多线程访问同一代码,不会产生不确定的结果。 LinkedBlockingQueue 由于LinkedBlockingQueue实现是线程安全的,实现了先进先出等特性,是作为生产者消费者的首选 ,LinkedBlockingQueue 可以指定容量,也可以不指定,不指定的话,默认最大是Integer.MAX_VALUE,其中主要用到put和take方法,put方法在队列满的时候会阻塞直到有队列成员被消费,take方法在队列空的时候会阻塞,直到有队列成员被放进来。 package cn.thread; import java.util.concurrent.BlockingQueue; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent

Java 实现线程安全的三种方式

穿精又带淫゛_ 提交于 2019-12-03 13:37:25
一个程序在运行起来的时候会转换成进程,通常含有多个线程。   通常情况下,一个进程中的比较耗时的操作(如长循环、文件上传下载、网络资源获取等),往往会采用多线程来解决。 比如显示生活中,银行取钱问题、火车票多个售票窗口的问题,通常会涉及到并发的问题,从而需要多线程的技术。   当进程中有多个并发线程进入一个重要数据的代码块时,在修改数据的过程中,很有可能引发线程安全问题,从而造成数据异常。例如,正常逻辑下,同一个编号的火车票只能售出一次,却由于线程安全问题而被多次售出,从而引起实际业务异常。 现在我们就以售票问题来演示线程安全的问题 1, 在不对多线程数据进行保护的情况下会引发的状况 public class ThreadUnSecurity { static int tickets = 10; class SellTickets implements Runnable{ @Override public void run() { // 未加同步时产生脏数据 while(tickets > 0) { System.out.println(Thread.currentThread().getName()+"--->售出第: "+tickets+" 票"); tickets--; try { Thread.sleep(1000); } catch

线程的相关技术总结

荒凉一梦 提交于 2019-12-03 10:46:43
--CountDownKatch CountDownLatch 内部维护了一个整数 n ,n(要大于等于0)在 当前线程 初始化 CountDownLatch 方法指定。当前线程调用 CountDownLatch 的 await() 方法阻塞当前线程,等待其他调用 CountDownLatch 对象的 CountDown() 方法的线程执行完毕。 其他线程调用该 CountDownLatch 的 CountDown() 方法,该方法会把 n-1 ,直到所有线程执行完成, n 等于 0 ,当前线程 就恢复执行 --CyclicBarrier CyclicBarrier 是一个同步辅助类,允许一组线程互相等待,直到到达某个公共屏障点(CommonBarrierPoint)。因为该 barrier 在释放等待线程后可以重用,所以称它为循环的 barrier 。 -- Semaphore Semaphore 直译为信号。实际上 Semaphore 可以看做是一个信号的集合。不同的线程能够从 Semaphore 中获取若干个信号量。当 Semaphore 对象持有的信号量不足时,尝试从 Semaphore 中获取信号的线程将会阻塞。直到其他线程将信号量释放以后,阻塞的线程会被唤醒,重新尝试获取信号量。 --说说 CountDownLatch 与 CyclicBarrier 区别

不管你年底换不换工作,了解下单例模式

女生的网名这么多〃 提交于 2019-12-03 07:36:47
1. 单例模式 什么是单例模式?简言之就是确保定义为单例模式的类在程序中有且只有一个实例。单例模式的特点: 只有一个实例 (只能有一个对象被创建) 自我实例化(类构造器私有) 对外提供获取实例的静态方法 2.单例模式的实现 常见的单例模式实现方式有五种: 2.1. 懒汉式 懒汉式(一般也称之为 饱汉式),具体代码实现如下: public class Singleton { /** * 自我实例化 */ private static Singleton singleton; /** * 构造方法私有 */ private Singleton() { System.out.println("创建单例实例..."); } /** * 对外提供获取实例的静态方法 */ public static Singleton getInstance() { if (null == singleton) { singleton = new Singleton(); } return singleton; } } 从代码实现中可以看到,实例并不是在一开始就是初始化的,而是在调用 **getInstance()**方法后才会产生单例,这种模式延迟初始化实例,但它并非是线程安全的。 public class SingleTonTest { /** * 多线程模式下测试懒汉模式是否线程安全 * *

不管你年底换不换工作,了解下单例模式

为君一笑 提交于 2019-12-03 07:27:23
1. 单例模式 什么是单例模式?简言之就是确保定义为单例模式的类在程序中有且只有一个实例。单例模式的特点: 只有一个实例 (只能有一个对象被创建) 自我实例化(类构造器私有) 对外提供获取实例的静态方法 2.单例模式的实现 常见的单例模式实现方式有五种: 2.1. 懒汉式 懒汉式(一般也称之为 饱汉式),具体代码实现如下: public class Singleton { /** * 自我实例化 */ private static Singleton singleton; /** * 构造方法私有 */ private Singleton() { System.out.println("创建单例实例..."); } /** * 对外提供获取实例的静态方法 */ public static Singleton getInstance() { if (null == singleton) { singleton = new Singleton(); } return singleton; } } 从代码实现中可以看到,实例并不是在一开始就是初始化的,而是在调用 **getInstance()**方法后才会产生单例,这种模式延迟初始化实例,但它并非是线程安全的。 public class SingleTonTest { /** * 多线程模式下测试懒汉模式是否线程安全 * *

JAVA多线程面试题

↘锁芯ラ 提交于 2019-12-03 03:58:44
前言 多线程分类中写了21篇多线程的文章,21篇文章的内容很多,个人认为,学习,内容越多、越杂的知识,越需要进行深刻的总结,这样才能记忆深刻,将知识变成自己的。这篇文章主要是对多线程的问题进行总结的,因此罗列了40个多线程的问题。 这些多线程的问题,有些来源于各大网站、有些来源于自己的思考。可能有些问题网上有、可能有些问题对应的答案也有、也可能有些各位网友也都看过,但是本文写作的重心就是 所有的问题都会按照自己的理解回答一遍,不会去看网上的答案 ,因此可能有些问题讲的不对,能指正的希望大家不吝指教。 40个问题汇总 1、多线程有什么用? 一个可能在很多人看来很扯淡的一个问题:我会用多线程就好了,还管它有什么用?在我看来,这个回答更扯淡。所谓"知其然知其所以然","会用"只是"知其然","为什么用"才是"知其所以然",只有达到"知其然知其所以然"的程度才可以说是把一个知识点运用自如。OK,下面说说我对这个问题的看法: (1)发挥多核CPU的优势 随着工业的进步,现在的笔记本、台式机乃至商用的应用服务器至少也都是双核的,4核、8核甚至16核的也都不少见,如果是单线程的程序,那么在双核CPU上就浪费了50%,在4核CPU上就浪费了75%。 单核CPU上所谓的"多线程"那是假的多线程,同一时间处理器只会处理一段逻辑,只不过线程之间切换得比较快,看着像多个线程"同时"运行罢了

单例模式的懒汉饿汉

旧巷老猫 提交于 2019-12-03 03:01:21
单例模式的三个特点:   1. 私有构造方法;   2. 内部创建静态对象;   3. 提供静态方法返回该静态对象; 单例设计模式主要有两种实现方法:饿汉式和懒汉式   饿汉式单例:在定义开始,便实例化自己。 class Singleton0 { //构造方法私有化 private Singleton0() { } //内部创建静态对象并实例化 private static Singleton0 s=new Singleton0(); //提供静态方法返回该静态对象 public static Singleton0 getsingle() { return s; } }   懒汉式单例:在第一次调用时实例化自己。 class Singleton1{ //构造方法私有化 private Singleton1() { } //内部创建静态对象 public static Singleton1 single=null; //提供静态方法返回该静态对象 public static Singleton1 getsingle() { //静态对象实例化 single=new Singleton1(); return single; } }   懒汉式与饿汉式的区别:     1. 线程安全:       饿汉式天生线程安全,可以直接用于多线程而不会出现问题。       懒汉式本身非线程安全

Java容器常见面试题

 ̄綄美尐妖づ 提交于 2019-12-03 01:28:58
1. Java 容器都有哪些? Java 容器分为 Collection 和 Map 两大类,其下又有很多子类,如下所示是Collection和Map的继承体系: 具体如下结构: Collection List ArrayList LinkedList Vector Stack Set HashSet LinkedHashSet TreeSet Map HashMap LinkedHashMap TreeMap ConcurrentHashMap Hashtable 2. ArrayList和LinkList的区别? ArrayList(数组结构) : 优点:get和set调用花费常数时间,也就是查询的速度快 缺点:新项的插入和现有项的删除代价昂贵,也就是添加删除的速度慢 LinkedList(链表结构) : 优点:新项的插入和和现有项的删除开销很小,即添加和删除的速度快 缺点:对get和set的调用花费昂贵,不适合做查询 面试中经常问到一些深入的东西,比如: 是否保证线程安全 : ArrayList 和 LinkedList 都是不同步的,也就是不保证线程安全; 底层数据结构 : Arraylist 底层使用的是Object数组;LinkedList 底层使用的是双向循环链表数据结构; 插入和删除是否受元素位置的影响 : ① ArrayList 采用数组存储

Java常用容器总结

好久不见. 提交于 2019-12-03 01:28:42
在工作中经常会碰到需要各种容器的场景,Java为我们提供了很多的容器,本文将对常用的一些容器做一个总结。 从Java的集合继承关系图中我们可以看到Java的容器一共分为List,Queue,Stack,Set,Map这五种,其中List,Stack,Queue其实在逻辑结构上几乎没有区别,Stack比较特殊,因为在实际开发中几乎不会被用到,不对Stack做相关总结。 一、List 非线程安全的List LinkedList,ArrayList 分别基于链表,数组实现。 线程安全的List Vector 通过给可能出现并发问题的public方法加上synchronized关键字来同步,性能极低,已被弃用。 Collections.synchronizedList(new ArrayList<>()) 这是Collections工具类提供一个方法可以将一个ArrayList变成线程安全的List,和Vector的区别主要是扩容方式不容,加锁方式不同,具体可以参考这篇博客 Vector和SynchronizedList区别 ,其实我个人感觉在线程安全方面的性能差别几乎没有,但是既然Vector已经被弃用了就用这个就可以。 Collections.synchronizedList(new LinkedList<>()) 和synchronizedList一样

Java线程安全的容器与介绍

假如想象 提交于 2019-12-03 01:28:24
Java基本容器介绍 Collection接口是集合类的根接口,Java中没有提供这个接口的直接的实现类。Set和List两个类继承于它。Set中不能包含重复的元素,也没有顺序来存放。而List是一个有序的集合,可以包含重复的元素。 而Map又是另一个接口,它和Collection接口没有关系。Map包含了key-value键值对,同一个Map里key是不能重复的,而不同key的value是可以相同的。 Java集合容器框架图: 1.1. List List在collection中的框架图: 1.1.1. ArrayList 1) ArrayList实现了可变大小的数组。它允许所有元素,包括null元素。ArrayList没有同步。 2)size,isEmpty,get,set方法运行时间为常数。但是add方法开销为分摊的常数,添加n个元素需要O(n)的时间。其他的方法运行时间为线性。Size是返回元素的个数。 3) 每个ArrayList实例都有一个容量(Capacity),即用于存储元素的数组的大小。这个容量可随着不断添加新元素而自动增加,但是增长算法并没有定义。当需要插入大量元素时,在插入前可以调用ensureCapacity方法来增加ArrayList的容量以提高插入效率。 4)和LinkedList一样,ArrayList也是非同步的(unsynchronized)。 5