![](https://img-blog.csdnimg.cn/20201014180756923.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
Java多线程编程
Burgess_Lee
对编程语言和新技术非常感兴趣,志同道合者我们一起来学习,如有好的建议或不对的地方, 还希望广大程序猿予以指正。
展开
-
CompletableFutrue用法
最近看书,看到这里发现JDK1.8新增的CompletableFuture类,更好的满足于异步IO(非阻塞IO)的方式编程。如果你已经对Future使用很熟悉的,那么我么说下缺点:1.如果提交了一个任务,但是执行太慢了,我通过其他路径已经获取到了任务结果,现在没法把这个任务结果,通知到正在执行的线程,所以必须主动取消或者一直等待它执行完成2.如果执行完之后,相对任务进行进一步处理,那么是...原创 2020-01-07 16:32:04 · 278 阅读 · 0 评论 -
09Java内存模型
关于java的内存模型,大家可以看一下关于jvm相关的知识。当然也可以参考一下之前我这边整理和转载的一些相关的知识,具体链接是https://blog.csdn.net/burgess_lee/article/category/7937013下面开始本篇博客内容的整理和学习。Java内存模型规范了Java虚拟机与计算机内存是如何协同工作的。Java虚拟机是一个完整的计算机的一个模型,因此这...转载 2018-09-07 11:58:00 · 90 阅读 · 0 评论 -
10Java同步块
Java 同步块(synchronized block)用来标记方法或者代码块是同步的。Java同步块用来避免竞争。本文介绍以下内容:Java同步关键字(synchronzied) 实例方法同步 静态方法同步 实例方法中同步块 静态方法中同步块 Java同步示例Java 同步关键字(synchronized)Java中的同步块用synchronized标记。同步块在Java中是...转载 2018-09-07 13:52:04 · 118 阅读 · 0 评论 -
11线程通信
线程通信的目标是使线程间能够互相发送信号。另一方面,线程通信使线程能够等待其他线程的信号。例如,线程B可以等待线程A的一个信号,这个信号会通知线程B数据已经准备好了。1、通过共享对象通信线程间发送信号的一个简单方式是在共享对象的变量里设置信号值。线程A在一个同步块里设置boolean型成员变量hasDataToProcess为true,线程B也在同步块里读取hasDataToProcess...转载 2018-09-07 14:15:12 · 90 阅读 · 0 评论 -
12ThreadLocal
Java中的ThreadLocal类可以让你创建的变量只被同一个线程进行读和写操作。因此,尽管有两个线程同时执行一段相同的代码,而且这段代码又有一个指向同一个ThreadLocal变量的引用,但是这两个线程依然不能看到彼此的ThreadLocal变量域。1、创建一个ThreadLocal对象private ThreadLocal myThreadLocal = new ThreadLoc...转载 2018-09-07 14:39:11 · 131 阅读 · 0 评论 -
22阻塞队列
阻塞队列与普通队列的区别在于,当队列是空的时,从队列中获取元素的操作将会被阻塞,或者当队列是满时,往队列里添加元素的操作会被阻塞。试图从空的阻塞队列中获取元素的线程将会被阻塞,直到其他的线程往空的队列插入新的元素。同样,试图往已满的阻塞队列中添加新元素的线程同样也会被阻塞,直到其他的线程使队列重新变得空闲起来,如从队列中移除一个或者多个元素,或者完全清空队列,下图展示了如何通过阻塞队列来合作:...转载 2018-09-13 09:22:16 · 87 阅读 · 0 评论 -
23线程池
线程池(Thread Pool)对于限制应用程序中同一时刻运行的线程数很有用。因为每启动一个新线程都会有相应的性能开销,每个线程都需要给栈分配一些内存等等。我们可以把并发执行的任务传递给一个线程池,来替代为每个并发执行的任务都启动一个新的线程。只要池里有空闲的线程,任务就会分配给一个线程执行。在线程池的内部,任务被插入一个阻塞队列(上一篇博文 ),线程池里的线程会去取这个队列里的任务。当一个新任务...转载 2018-09-13 09:37:19 · 124 阅读 · 0 评论 -
13死锁
死锁是两个或更多线程阻塞着等待其它处于死锁状态的线程所持有的锁。死锁通常发生在多个线程同时但以不同的顺序请求同一组锁的时候。例如,如果线程1锁住了A,然后尝试对B进行加锁,同时线程2已经锁住了B,接着尝试对A进行加锁,这时死锁就发生了。线程1永远得不到B,线程2也永远得不到A,并且它们永远也不会知道发生了这样的事情。为了得到彼此的对象(A和B),它们将永远阻塞下去。这种情况就是一个死锁。这...转载 2018-09-07 15:21:46 · 87 阅读 · 0 评论 -
14避免死锁
在有些情况下死锁是可以避免的。加锁顺序当多个线程需要相同的一些锁,但是按照不同的顺序加锁,死锁就很容易发生。如果能确保所有的线程都是按照相同的顺序获得锁,那么死锁就不会发生。看下面这个例子:Thread 1: lock A lock BThread 2: wait for A lock C (when A locked)Thread 3: wa...转载 2018-09-07 15:52:52 · 260 阅读 · 0 评论 -
24Java并发编程之CAS
CAS(Compare and swap)比较和替换是设计并发算法时用到的一种技术。简单来说,比较和替换是使用一个期望值和一个变量的当前值进行比较,如果当前变量的值与我们期望的值相等,就使用一个新值替换当前变量的值。这听起来可能有一点复杂但是实际上你理解之后发现很简单,接下来,让我们跟深入的了解一下这项技术。CAS的使用场景在程序和算法中一个经常出现的模式就是“check and act”...转载 2018-09-13 09:53:29 · 94 阅读 · 0 评论 -
25剖析同步器
虽然许多同步器(如锁,信号量,阻塞队列等)功能上各不相同,但它们的内部设计上却差别不大。换句话说,它们内部的的基础部分是相同(或相似)的。了解这些基础部件能在设计同步器的时候给我们大大的帮助。这就是本文要细说的内容。注:本文的内容是哥本哈根信息技术大学一个由Jakob Jenkov,Toke Johansen和Lars Bjørn参与的M.Sc.学生项目的部分成果。在此项目期间我们咨询Doug...转载 2018-09-13 10:21:34 · 125 阅读 · 0 评论 -
26非阻塞算法
在并发上下文中,非阻塞算法是一种允许线程在阻塞其他线程的情况下访问共享状态的算法。在绝大多数项目中,在算法中如果一个线程的挂起没有导致其它的线程挂起,我们就说这个算法是非阻塞的。为了更好的理解阻塞算法和非阻塞算法之间的区别,我会先讲解阻塞算法然后再讲解非阻塞算法。阻塞并发算法一个阻塞并发算法一般分下面两步:执行线程请求的操作 阻塞线程直到可以安全地执行操作很多算法和并发数据结构...转载 2018-09-13 14:00:17 · 142 阅读 · 0 评论 -
27阿姆达尔定律
阿姆达尔定律可以用来计算处理器平行运算之后效率提升的能力。阿姆达尔定律因Gene Amdal 在1967年提出这个定律而得名。绝大多数使用并行或并发系统的开发者有一种并发或并行可能会带来提速的感觉,甚至不知道阿姆达尔定律。不管怎样,了解阿姆达尔定律还是有用的。我会首先以算术的方式介绍阿姆达尔定律定律,然后再用图表演示一下。阿姆达尔定律定义一个程序(或者一个算法)可以按照是否可以被并行化...转载 2018-09-13 14:27:57 · 262 阅读 · 0 评论 -
21信号量
Semaphore(信号量) 是一个线程同步结构,用于在线程间传递信号,以避免出现信号丢失(译者注:下文会具体介绍),或者像锁一样用于保护一个关键区域。自从5.0开始,jdk在java.util.concurrent包里提供了Semaphore 的官方实现,因此大家不需要自己去实现Semaphore。但是还是很有必要去熟悉如何使用Semaphore及其背后的原理一、简单的Semaphore实现...转载 2018-09-12 16:38:51 · 116 阅读 · 0 评论 -
20重入锁死
重入锁死与死锁和嵌套管程锁死非常相似。锁和读写锁两篇文章中都有涉及到重入锁死的问题。当一个线程重新获取锁,读写锁或其他不可重入的同步器时,就可能发生重入锁死。可重入的意思是线程可以重复获得它已经持有的锁。Java的synchronized块是可重入的。因此下面的代码是没问题的:public class Reentrant{ public synchronized outer(){ ...转载 2018-09-12 14:42:20 · 86 阅读 · 0 评论 -
01并发和多线程介绍
随着计算的的发展,由单任务在一个时间点只能执行单一程序,到多个任务同一个时间点共享用一个CPU,执行多个任务。这个过程的实现完全依赖于计算机操作系统的发展。(此处并不是真正意义上的“同一时间点”)。所以现在开发,不能只考虑单个CPU的执行效率,资源使用情况,而更多的是要考虑到充分利用各个资源,使得其他的程序也能利用到这些资源。后来出现的多线程技术,实现了一个程序可以由多个线程来进行执行,从而实...转载 2018-09-05 09:55:50 · 110 阅读 · 0 评论 -
02多线程优点
总的概括来说,多线程的优点是:资源利用率更高 程序设计在某些情况下更简单 程序响应更快下面逐一进行一下说明:资源利用率更好想象一下,一个应用程序需要从本地文件系统中读取和处理文件的情景。比方说,从磁盘读取一个文件需要5秒,处理一个文件需要2秒。处理两个文件则需要: 1 5秒读取文件A 2 2秒处理文件A 3 5秒读...转载 2018-09-05 10:08:08 · 86 阅读 · 0 评论 -
03多线程的代价
从一个单线程的应用到一个多线程的应用并不仅仅带来好处,它也会有一些代价。不要仅仅为了使用多线程而使用多线程。而应该明确在使用多线程时,能多获取的好处比所付出的代价大的时候,才使用多线程。如果存在疑问,应该尝试测量一下应用程序的性能和响应能力,而不只是猜测。设计更复杂虽然有一些多线程应用程序比单线程的应用程序要简单,但其他的一般都更复杂。在多线程访问共享数据的时候,这部分代码需要特别的注意。...转载 2018-09-05 10:41:13 · 76 阅读 · 0 评论 -
04并发编程模型
并发系统可以采用多种并发编程模型来实现。并发模型指定了系统中的线程如何通过协作来完成分配给它们的作业。不同的并发模型采用不同的方式拆分作业,同时线程间的协作和交互方式也不相同。这篇并发模型教程将会较深入地介绍目前(2015年,本文撰写时间)比较流行的几种并发模型。并发模型与分布式系统之间的相似性本文所描述的并发模型类似于分布式系统中使用的很多体系结构。在并发系统中线程之间可以相互通信。在分...转载 2018-09-05 13:49:56 · 108 阅读 · 0 评论 -
05创建和运行java的线程
Java线程类也是一个Object类,它的实例都继承自java.lang.Thread或其子类。 可以用如下方式用java中创建一个线程:Thread thread = new Thread();启动该线程调用start()方法。编写线程运行时执行的代码有两种方式:一种是创建Thread子类的一个实例并重写run方法,第二种是创建类的时候实现Runnable接口。接下来我们会具体...转载 2018-09-05 16:12:43 · 84 阅读 · 0 评论 -
06竞态条件与临界区
在同一程序中运行多个线程本身不会导致问题,问题在于多个线程访问了相同的资源。如,同一内存区(变量,数组,或对象)、系统(数据库,web services等)或文件。实际上,这些问题只有在一或多个线程向这些资源做了写操作时才有可能发生,只要资源没有发生变化,多个线程读取相同的资源就是安全的。public class Counter { protected long count = 0; p...转载 2018-09-06 13:43:04 · 109 阅读 · 0 评论 -
07线程安全与共享资源
允许被多个线程同时执行的代码称作线程安全的代码。线程安全的代码不包含竞态条件。当多个线程同时更新共享资源时会引发竞态条件。因此,了解Java线程执行时共享了什么资源很重要。局部变量局部变量存储在线程自己的栈中。也就是说,局部变量永远也不会被多个线程共享。所以,基础类型的局部变量是线程安全的。局部的对象引用对象的局部引用和基础类型的局部变量不太一样。尽管引用本身没有被共享,但引用所指...转载 2018-09-06 16:55:23 · 115 阅读 · 0 评论 -
15饥饿和公平
前一段时间工作有些忙碌,连续好几天,没有坚持写,甚是有些不舒坦。于是今天继续。上篇博文说到了死锁,不了解的小伙伴可以看一下上面两篇关于死锁方面的介绍。本篇博文主要是对饥饿和公平进行介绍。如果一个线程因为CPU时间全部被其他线程抢走而得不到CPU运行时间,这种状态被称之为“饥饿”。而该线程被“饥饿致死”正是因为它得不到CPU运行时间的机会。解决饥饿的方案被称之为“公平性” – 即所有线程均能公平...转载 2018-09-12 10:52:55 · 223 阅读 · 0 评论 -
16嵌套管程锁死
嵌套管程锁死类似于死锁, 下面是一个嵌套管程锁死的场景:线程1获得A对象的锁。线程1获得对象B的锁(同时持有对象A的锁)。线程1决定等待另一个线程的信号再继续。线程1调用B.wait(),从而释放了B对象上的锁,但仍然持有对象A的锁。线程2需要同时持有对象A和对象B的锁,才能向线程1发信号。线程2无法获得对象A上的锁,因为对象A上的锁当前正被线程1持有。线程2一直被阻塞,等待线...转载 2018-09-12 11:05:09 · 94 阅读 · 0 评论 -
17Slipped Conditions
所谓Slipped conditions,就是说, 从一个线程检查某一特定条件到该线程操作此条件期间,这个条件已经被其它线程改变,导致第一个线程在该条件上执行了错误的操作。这里有一个简单的例子:public class Lock { private boolean isLocked = true; public void lock(){ synchronized...转载 2018-09-12 11:29:11 · 126 阅读 · 0 评论 -
18Java中的锁
锁像synchronized同步块一样,是一种线程同步机制,但比Java中的synchronized同步块更复杂。因为锁(以及其它更高级的线程同步机制)是由synchronized同步块的方式实现的,所以我们还不能完全摆脱synchronized关键字(译者注:这说的是Java 5之前的情况)。自Java 5开始,java.util.concurrent.locks包中包含了一些锁的实现,因此...转载 2018-09-12 13:33:20 · 132 阅读 · 0 评论 -
19Java中的读/写锁
相比上篇博文中里Lock实现,读写锁更复杂一些。假设你的程序中涉及到对一些共享资源的读和写操作,且写操作没有读操作那么频繁。在没有写操作的时候,两个线程同时读一个资源没有任何问题,所以应该允许多个线程能在同时读取共享资源。但是如果有一个线程想去写这些共享资源,就不应该再有其它线程对该资源进行读或写(译者注:也就是说:读-读能共存,读-写不能共存,写-写不能共存)。这就需要一个读/写锁来解决这个问题...转载 2018-09-12 13:59:35 · 107 阅读 · 0 评论 -
00.开篇介绍
经过选择和筛选,打算按照又一位大神的路线,进行一下多线程方面知识的查漏补缺。于是从明天开始,开启新的模块,Java多线程编程方面,有喜欢一起研究的同学,欢迎你们的加入,希望我的理解和我的坚持能让你有所获,让我们一起共同进步。...原创 2018-09-04 21:44:46 · 97 阅读 · 0 评论