线程阻塞

BlockingQueue(阻塞队列)详解

*爱你&永不变心* 提交于 2020-03-24 10:02:50
注意:该随笔内容完全引自http://wsmajunfeng.iteye.com/blog/1629354,写的很好,非常感谢,复制过来算是个积累,怕以后找不到。 一. 前言   在新增的Concurrent包中,BlockingQueue很好的解决了多线程中,如何高效安全“传输”数据的问题。通过这些高效并且线程安全的队列类,为我们快速搭建高质量的多线程程序带来极大的便利。本文详细介绍了BlockingQueue家庭中的所有成员,包括他们各自的功能以及常见使用场景。 二. 认识BlockingQueue   阻塞队列,顾名思义,首先它是一个队列,而一个队列在数据结构中所起的作用大致如下图所示:   从上图我们可以很清楚看到,通过一个共享的队列,可以使得数据由队列的一端输入,从另外一端输出;   常用的队列主要有以下两种:(当然通过不同的实现方式,还可以延伸出很多不同类型的队列,DelayQueue就是其中的一种)     先进先出(FIFO):先插入的队列的元素也最先出队列,类似于排队的功能。从某种程度上来说这种队列也体现了一种公平性。     后进先出(LIFO):后插入队列的元素最先出队列,这种队列优先处理最近发生的事件。   多线程环境中,通过队列可以很容易实现数据共享,比如经典的“生产者”和“消费者”模型中,通过队列可以很便利地实现两者之间的数据共享

多线程

泪湿孤枕 提交于 2020-03-24 10:02:09
基础概念 多线程: 进程:一个程序中至少一个进程,一个进程至少一个线程。 用户线程,正常情况下创建 守护线程:需要手动创建 线程是通过调用start()方法准备启动 线程调度! 线程的创建方式:两种, 1.Thread类派生,覆盖run() 2.实现Runnable接口 线程调度 什么是线程调度?线程是不可控的,那么如何干预线程的执行? -等待: 让某一个线程进入等待状态,等到条件满足后,被其他线程唤醒 等待需要在同步环境,未持锁则报错 等待后被唤醒,需重新经过持锁状态,然后回到就绪状态,等待资源分配 -休眠: 是让当前线程进入休眠状态,这是Thread的静态方法,休眠只能自己响 1.至少消耗指定时间,(等待资源分配) 2.休眠不可以被唤醒,休眠必须有参数! -让步: 1.不建议使用优先级、礼让!因为最终结果不可控! 2.使用,先设优先级,再启动线程 3.让步是不可控的 4.没有经过阻塞,直接回到就绪状态 -合并线程: 1.是让并行线程,变为串行状态 2.先执行,再合并 3.什么情况下要合并线程? 某个线程要等到另外一个线程结果时,需要合并,已等待前面的结果。 -守护线程:(用户线程的区别--所有用户线程执行完毕后,其他所有守护线程killed) 1.当用户线程全部执行完毕后,守护线程立即停止,无论他执行到哪儿 2.守护线程,先设置,再执行。 应用情况:定时任务;清理日志

Java_多线程(1)

ぃ、小莉子 提交于 2020-03-24 07:16:21
前面写了这么多篇java的基础,这篇我们终于进入到了java中比较复杂的部分——java多线程。 什么是线程? 介绍线程之前,我们必须先了解下进程。 进程 :是程序的一次动态执行过程。比如你打开了IE浏览器,从它打开的时刻就启动了一个进程。 多进程 :多进程就像打开了多个程序,比如你边玩QQ,边用网易云听歌,还可以浏览网页,多个任务同时进行。 线程 :比进程更小的执行单位,通常一个进程拥有1-n个线程。 多线程 :指在同一个程序(进程)中能够同时处理多个任务,而这些任务就对应多个线程。比如浏览器可以同时下载多个图片;比如ABC三个用户同时访问淘宝,淘宝的服务器收到A用户的请求后,为A创建了一个线程,BC用户同样拥有自己对应的线程。 注意 :多线程不是为了提高程序的执行速度(甚至降低性能),而是提高应用程序的使用效率。 线程的生命周期? 每一个生命周期也是一种状态。 1)创建:创建一个新的线程对象; 2)就绪:线程对象创建后,其他线程调用了该对象的start()方法,该线程被放入可运行的线程池中,等待获取CPU的使用权; 3)运行:就绪状态的线程获取了CPU,执行; 4)阻塞:由于某种原因,线程暂停; 5)死亡:线程执行完成或异常抛出,该线程生命周期结束。 Java实现多线程: java中实现多线程有两种方法,一种是继承Thread类,一种是实现Runnable接口。 注意:准确来说

深入理解Synchronized

拥有回忆 提交于 2020-03-23 22:13:08
3 月,跳不动了?>>> 目前在Java中存在两种锁机制:synchronized和Lock,Lock接口及其实现类是JDK5增加的内容,其作者是大名鼎鼎的并发专家Doug Lea。本文并不比较synchronized与Lock孰优孰劣,只是介绍二者的实现原理。 数据同步需要依赖锁,那锁的同步又依赖谁?synchronized给出的答案是在软件层面依赖JVM,而Lock给出的方案是在硬件层面依赖特殊的CPU指令,大家可能会进一步追问:JVM底层又是如何实现synchronized的? 本文所指说的JVM是指Hotspot的6u23版本,下面首先介绍synchronized的实现: synrhronized关键字简洁、清晰、语义明确,因此即使有了Lock接口,使用的还是非常广泛。其应用层的语义是可以把任何一个非null对象作为"锁",当synchronized作用在方法上时,锁住的便是对象实例(this);当作用在静态方法时锁住的便是对象对应的Class实例,因为Class数据存在于永久带,因此静态方法锁相当于该类的一个全局锁;当synchronized作用于某一个对象实例时,锁住的便是对应的代码块。在HotSpot JVM实现中,锁有个专门的名字:对象监视器。 1. 线程状态及状态转换 当多个线程同时请求某个对象监视器时,对象监视器会设置几种状态用来区分请求的线程:

synchronized实现原理

一个人想着一个人 提交于 2020-03-23 22:12:53
3 月,跳不动了?>>> 目前在Java中存在两种锁机制:synchronized和Lock。数据同步需要依赖锁,那锁时如何实现的呢,synchronized给出的答案是软件层面依赖JVM,而Lock给出的方案是在硬件层面依赖特殊的CPU指令。 下面先介绍synchronized的实现: synchronized 是关键字,即使有了Lock接口(Lock能够实现synchronized能够实现的所有功能),使用的还是非常广泛。其应用层的语义是可以把任何一个非nul对象作为锁,当synchronized作用在方法上时,锁住的对象是实例对象(this);当作用在静态方法时锁住的对象时对象对应的Class实例,因为Class数据存在于永久带,因此静态方法锁相当于类的一个全局锁;当synchronized作用于某一个对象实例时,锁住的便是对应的代码块。在JVM实现中,所有一个专门的名字:对象监视器 线程状态与状态的转换 当多个线程同时请求某个对象监视器时,对象监视器会设置几种状态来区分请求的线程 Contention List:所有请求锁的线程将被首先放置到竞争队列。Contention List是一个虚拟队列,原因在于Contention List是一个由Node及next指针逻辑构成,并不存在一个Queue的数据结构。ContentionList是一个后进先出(LIFO)队列。

Java多线程并发09——如何实现线程间与线程内数据共享

一个人想着一个人 提交于 2020-03-23 20:42:20
本文将为各位带来 Java 阻塞队列相关只是。关注我的公众号「Java面典」了解更多 Java 相关知识点。 线程间数据共享 Java 里面进行多线程通信的主要方式就是共享内存的方式,共享内存主要的关注点有两个:可见性和有序性原子性。Java 内存模型(JMM)解决了可见性和有序性的问题,而锁解决了原子性的问题,理想情况下我们希望做到“同步”和“互斥”。有以下常规实现方法: 将数据抽象成一个类 将数据抽象成一个类,并将对这个数据的操作作为这个类的方法,这么设计可以和容易做到同步,只要在方法上加”synchronized“。 public class MyData { private int j = 0; public synchronized void add() { j++; System.out.println("线程" + Thread.currentThread().getName() + "j 为:" + j); } public synchronized void dec() { j--; System.out.println("线程" + Thread.currentThread().getName() + "j 为:" + j); } public int getData() { return j; } } public class AddRunnable

并发队列

对着背影说爱祢 提交于 2020-03-23 19:22:15
一、介绍 在并发队列上JDK提供了两套实现,一个是以ConcurrentLinkedQueue为代表的高性能队 列,一个是以BlockingQueue接口为代表的阻塞队列,无论哪种都继承自Queue。 二、ConcurrentLinkedQueue 1. 介绍 ConcurrentLinkedQueue: 是一个适用于高并发场景下的队列,通过无锁的方式,实现 了高并发状态下的高性能,通常ConcurrentLinkedQueue性能好于BlockingQueue.它 是一个基于链接节点的无界线程安全队列。该队列的元素遵循先进先出的原则。头是最先 加入的,尾是最近加入的,该队列不允许null元素。 2. 重要方法: add 和offer() 都是加入元素的方法(在ConcurrentLinkedQueue中这俩个方法没有任何区别) poll() 和peek() 都是取头元素节点,区别在于前者会删除元素,后者不会。 3. Java代码: @Test public void testConcurrentLinkedDeque() { ConcurrentLinkedQueue<String> concurrentLinkedQueue = new ConcurrentLinkedQueue<String>(); concurrentLinkedQueue.offer("大都督");

【Go专家编程】调度模型

社会主义新天地 提交于 2020-03-23 17:47:41
3 月,跳不动了?>>> 线程模型 线程可分为用户线程和内核线程,用户线程由用户创建、同步和销毁,内核线程则由内核来管理。 根据用户线程管理方式的不同,分为三种线程模型。 一种是N:1模型,即N个用户线程运行在1个内核线程中,优点是用户线程上下文切换快,缺点是无法充分利用CPU多核的算力。 另一种是1:1模型,即每个用户线程对应一个内核线程,优点是充分利用CPU,缺点是线程上下文切换较慢。 Go实现的是M:N模型,即前两种模型的组合,M个用户线程(协程)运行在N个线程中,优点是充分利用CPU的算力且协程上下文切换快,缺点则是该模型的调度算法较为复杂。 Go调度器模型 Go协程调度模型中包含三个关键实体,Machine(简称M)、Processor(简称P)和Goroutine(简称G)。 M(Machine):工作线程,它由操作系统调度; P(Processor):处理器(Go定义的一个摡念,不是指CPU),包含运行Go代码的必要资源,也有调度goroutine的能力。 G(Goroutine): 即Go协程,每个go关键字都会创建一个协程。 M必须持有P才可以执行代码,跟系统中的其他线程一样,M也会被系统调用阻塞。 来源: oschina 链接: https://my.oschina.net/renhc/blog/3209215

Java多线程开发技巧

橙三吉。 提交于 2020-03-23 16:42:30
3 月,跳不动了?>>> 很多开发者谈到Java多线程开发,仅仅停留在new Thread(...).start()或直接使用Executor框架这个层面,对于线程的管理和控制却不够深入,通过读《Java并发编程实践》了解到了很多不为我知但又非常重要的细节,今日整理如下。 不应用线程池的缺点 有些开发者图省事,遇到需要多线程处理的地方,直接new Thread(...).start(),对于一般场景是没问题的,但如果是在并发请求很高的情况下,就会有些隐患: 新建线程的开销。线程虽然比进程要轻量许多,但对于JVM来说,新建一个线程的代价还是挺大的,决不同于新建一个对象 资源消耗量。没有一个池来限制线程的数量,会导致线程的数量直接取决于应用的并发量,这样有潜在的线程数据巨大的可能,那么资源消耗量将是巨大的 稳定性。当线程数量超过系统资源所能承受的程度,稳定性就会成问题 制定执行策略 在每个需要多线程处理的地方,不管并发量有多大,需要考虑线程的执行策略 任务以什么顺序执行 可以有多少个任何并发执行 可以有多少个任务进入等待执行队列 系统过载的时候,应该放弃哪些任务?如何通知到应用程序? 一个任务的执行前后应该做什么处理 线程池的类型 不管是通过Executors创建线程池,还是通过Spring来管理,都得清楚知道有哪几种线程池: FixedThreadPool:定长线程池

死磕 java集合之LinkedTransferQueue源码分析

耗尽温柔 提交于 2020-03-23 16:25:06
问题 (1)LinkedTransferQueue是什么东东? (2)LinkedTransferQueue是怎么实现阻塞队列的? (3)LinkedTransferQueue是怎么控制并发安全的? (4)LinkedTransferQueue与SynchronousQueue有什么异同? 简介 LinkedTransferQueue是LinkedBlockingQueue、SynchronousQueue(公平模式)、ConcurrentLinkedQueue三者的集合体,它综合了这三者的方法,并且提供了更加高效的实现方式。 继承体系 LinkedTransferQueue实现了TransferQueue接口,而TransferQueue接口是继承自BlockingQueue的,所以LinkedTransferQueue也是一个阻塞队列。 TransferQueue接口中定义了以下几个方法: // 尝试移交元素 boolean tryTransfer(E e); // 移交元素 void transfer(E e) throws InterruptedException; // 尝试移交元素(有超时时间) boolean tryTransfer(E e, long timeout, TimeUnit unit) throws InterruptedException; //