多线程

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接口。 注意:准确来说

java基础巩固笔记(5)-多线程之传统多线程

寵の児 提交于 2020-03-23 23:11:06
3 月,跳不动了?>>> java基础巩固笔记(5)-多线程之传统多线程 标签: java [TOC] 传统线程技术 传统创建线程方式 1.继承Thread类,覆盖run方法 Thread t = new Thread(); t.start(); 2.实现Runnable接口 Runnable不是线程,是线程要运行的代码的宿主。 1.看看Thread类源码,捋清Runnable,target,run,start关系 Runnable 是一个接口 target 是 Thread 类中类型为 Runnable ,名为 target 的属性 run 是 Thread 类实现了 Runnable 的接口,重写的方法。 start 是启动线程的方法 在 Thread 类中,调用关系为: start -> start0 -> run -> target.run Thread 类的 run 方法源码 public void run() { if (target != null) { target.run(); } } Thread 类的 target 属性 /* What will be run. */ private Runnable target; target 属性由 private void init(ThreadGroup g, Runnable target, String name

传统线程互斥技术

最后都变了- 提交于 2020-03-23 22:49:35
3 月,跳不动了?>>> 使用synchronized代码块及其原理? 使用synchronized方法? 分析静态方法所使用的同步监视器对象是什么? 一、代码实现 1、同一对象锁 /** * @Title: TraditionalThreadSynchronized.java * @Package com.lh.threadtest * @Description: TODO * @author Liu * @date 2018年1月15日 下午6:38:24 * @version V1.0 */ package com.lh.threadtest.t3; import java.util.concurrent.TimeUnit; /** * @ClassName: TraditionalThreadSynchronized * @Description: 传统线程互斥技术 * @author Liu * @date 2018年1月15日 下午6:38:24 * */ public class TraditionalThreadSynchronized { /*** * @Title: main * @Description: TODO * @param @param args * @return void * @throws */ public static void main

自旋锁学习系列(3):指数后退技术

可紊 提交于 2020-03-23 21:48:51
3 月,跳不动了?>>> 上一篇 中分析了测试锁的两种实现TASLock和TTASLock,主要对这两种锁的性能进行了分析。对于TTASLock,我们知道比TASLock性能上要好很多,具体分析已经讲过了。我们最后也说了,TTASLock虽然比TASLock大有改进,但是在性能上还是不够理想。这一篇的目的就是针对TTASLock做一下改进。 我们再来看一下TTASLock的实现源码和加锁的流程图: /** * * Test test and set lock * */ public class TTASLock { private AtomicBoolean state = new AtomicBoolean(false); // 加锁 public void lock() { while (true) { while (state.get()) { // 自旋 } if (!state.getAndSet(true)) { break; } } } // 解锁 public void unlock() { state.set(false); } } 加锁流程图如下: 从上文我们知道,对于TTASLock锁,性能问题主要出现在解锁上。一旦一个已经获得锁的线程执行解锁操作。其他线程都会产生缓存缺失,将会由”本地自旋”转变为从共享服务器中去获取状态值。这会消耗大量的总线资源。所以

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 16:48:09
操作系统的设计,因此可以归结为三点: (1)以多进程形式,允许多个任务同时运行; (2)以多线程形式,允许单个任务分成不同的部分运行; (3)提供协调机制,一方面防止进程之间和线程之间产生冲突,另一方面允许进程之间和线程之间共享资源。 2. 线程与进程的区别? 程序: 完成某种功能的一段代码。静态概念。 任务: 程序完成的一个活动。既可以是一个进程,也可以是一个线程。 进程: 程序的一次执行过程。一个独立的进程在内存中有自己的数据空间和代码空间。它所拥有的数据变量属于它自己。 线程: 线程是进程的一个执行序列。同一个进程创建的多个线程可以共享进程的一些资源,如全局变量,同时,多个线程可以有自己的栈空间,线程的局部变量只属于这个线程。 线程可以有自己的堆栈和局部变量,但线程没有单独的地址空间,因此一个线程死掉就等于整个进程死掉,所以线程的健壮性不如进程。但进程切换时,系统开销大,因此 资源利用率低。 对于一些要求同时运行且要共享资源的并发操作,只能用线程,而不能用进程。 总结:1. 一个线程只能同时属于一个进程,一个进程可以有多个线程,且至少有一个线程。 2. 同一进程的所有线程共享进程的所有资源。有些资源的访问需要线程之间互斥访问。 3. 真正在处理机上运行的是线程,而不是进程。 4. 同步问题: 不同进程的线程之间利用消息通信的方式实现同步。 线程与进程的区别? 1、

Java多线程开发技巧

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

Java线程池相关

六月ゝ 毕业季﹏ 提交于 2020-03-23 16:38:39
3 月,跳不动了?>>> 线程池的规则与参数: 1. corePoolSize:核心线程数 核心线程会一直存活,及时没有任务需要执行 当线程数小于核心线程数时,即使有线程空闲,线程池也会优先创建新线程处理 设置allowCoreThreadTimeout=true(默认false)时,核心线程会超时关闭 2. queueCapacity:任务队列容量(阻塞队列) 当核心线程数达到最大时,新任务会放在队列中排队等待执行 3. maxPoolSize:最大线程数 当线程数>=corePoolSize,且任务队列已满时。线程池会创建新线程来处理任务 当线程数>=corePoolSize 且队列未满时,不再创建新线程 当线程数=maxPoolSize,且任务队列已满时,线程池会拒绝处理任务而抛出异常 4. keepAliveTime:非核心线程空闲时间 当线程空闲时间达到keepAliveTime时,线程会退出,直到线程数量=corePoolSize 5. allowCoreThreadTimeout:允许核心线程超时 默认为false;设置为true时,核心线程也会在keepAliveTime后退出。 6. rejectedExecutionHandler:任务拒绝处理器 当线程数已经达到maxPoolSize,切队列已满,会拒绝新任务 shutdown()后的等待期内提交的任务