AngrySea.Java.多线程
文章平均质量分 85
学习记录,Java多线程原理和要点
DeepSea.QQ
不要假装去努力,结果不会陪着你演戏。
展开
-
Java多线程学习四十三:
本课时我们主要讲解 final 的三种用法。final 的作用final 是 Java 中的一个关键字,简而言之,final 的作用意味着“这是无法改变的”。不过由于 final 关键字一共有三种用法,它可以用来修饰变量、方法或者类,而且在修饰不同的地方时,效果、含义和侧重点也会有所不同,所以我们需要把这三种情况分开介绍。我们先来看一下 final 修饰变量的情况。final 修饰变量作用关键字 final 修饰变量的作用是很明确的,那就是意味着这个变量一旦被赋值就不能被修改了,.转载 2021-04-14 22:00:01 · 240 阅读 · 0 评论 -
Java多线程学习四十二:有哪些解决死锁问题的策略和哲学家就餐问题
线上发生死锁应该怎么办如果线上环境发生了死锁,那么其实不良后果就已经造成了,修复死锁的最好时机在于“防患于未然”,而不是事后补救。就好比发生火灾时,一旦着了大火,想要不造成损失去扑灭几乎已经不可能了。死锁也是一样的,如果线上发生死锁问题,为了尽快减小损失,最好的办法是保存 JVM 信息、日志等“案发现场”的数据,然后立刻重启服务,来尝试修复死锁。为什么说重启服务能解决这个问题呢?因为发生死锁往往要有很多前提条件的,并且当并发度足够高的时候才有可能会发生死锁,所以重启后再次立刻发生死锁的几率并不是很大,转载 2021-04-12 22:30:46 · 219 阅读 · 0 评论 -
Java多线程学习四十一:死锁的四个条件和快速定位死锁
发生死锁的 4 个必要条件要想发生死锁有 4 个缺一不可的必要条件,我们一个个来看:第 1 个叫互斥条件,它的意思是每个资源每次只能被一个线程(或进程,下同)使用,为什么资源不能同时被多个线程或进程使用呢?这是因为如果每个人都可以拿到想要的资源,那就不需要等待,所以是不可能发生死锁的。第 2 个是请求与保持条件,它是指当一个线程因请求资源而阻塞时,则需对已获得的资源保持不放。如果在请求资源时阻塞了,并且会自动释放手中资源(例如锁)的话,那别人自然就能拿到我刚才释放的资源,也就不会形成死锁...转载 2021-04-12 22:23:32 · 281 阅读 · 0 评论 -
Java多线程学习四十:如何写一个必然死锁的例子
死锁是什么?有什么危害?什么是死锁发生在并发中首先你要知道,死锁一定发生在并发场景中。我们为了保证线程安全,有时会给程序使用各种能保证并发安全的工具,尤其是锁,但是如果在使用过程中处理不得当,就有可能会导致发生死锁的情况。互不相让死锁是一种状态,当两个(或多个)线程(或进程)相互持有对方所需要的资源,却又都不主动释放自己手中所持有的资源,导致大家都获取不到自己想要的资源,所有相关的线程(或进程)都无法继续往下执行,在未改变这种状态之前都不能向前推进,我们就把这种状态称为死锁状态,认为它们发生转载 2021-04-11 20:55:09 · 188 阅读 · 0 评论 -
Java多线程学习三十九:CAS 有什么缺点?
CAS 有哪几个主要的缺点。首先,CAS 最大的缺点就是 ABA 问题。决定 CAS 是否进行 swap 的判断标准是“当前的值和预期的值是否一致”,如果一致,就认为在此期间这个数值没有发生过变动,这在大多数情况下是没有问题的。但是在有的业务场景下,我们想确切知道从上一次看到这个值以来到现在,这个值是否发生过变化。例如,这个值假设从 A 变成了 B,再由 B 变回了 A,此时,我们不仅认为它发生了变化,并且会认为它变化了两次。在这种场景下,我们使用 CAS,就看不到这两次的变化,因为仅.转载 2021-04-11 20:43:04 · 236 阅读 · 0 评论 -
Java多线程学习三十八:你知道什么是 CAS 吗
CAS 简介CAS 其实是我们面试中的常客,因为它是原子类的底层原理,同时也是乐观锁的原理,所以当你去面试的时候,经常会遇到这样的问题“你知道哪些类型的锁”?你可能会回答“悲观锁和乐观锁”,那么下一个问题很有可能是问乐观锁的原理,也就是和 CAS 相关的问题,当然也有可能会继续深入问你 CAS 的应用场景或者是缺点等问题。在本课时和接下来的这两个课时里,我将带领你学习如何回答这些问题。首先我们来看一下 CAS 是什么,它的英文全称是 Compare-And-Swap,中文叫做“比较并交换”,它是一转载 2021-04-11 20:29:29 · 129 阅读 · 0 评论 -
Java多线程学习三十七:volatile 的作用是什么?与 synchronized 有什么异同
volatile 是什么首先我们就来介绍一下 volatile,它是 Java 中的一个关键字,是一种同步机制。当某个变量是共享变量,且这个变量是被 volatile 修饰的,那么在修改了这个变量的值之后,再读取该变量的值时,可以保证获取到的是修改后的最新的值,而不是过期的值。相比于 synchronized 或者 Lock,volatile 是更轻量的,因为使用 volatile 不会发生上下文切换等开销很大的情况,不会让线程阻塞。但正是由于它的开销相对比较小,所以它的效果,也就是能力,相对也小转载 2021-04-10 22:48:48 · 223 阅读 · 0 评论 -
Java多线程学习三十六:主内存和工作内存的关系
CPU 有多级缓存,导致读的数据过期由于 CPU 的处理速度很快,相比之下,内存的速度就显得很慢,所以为了提高 CPU 的整体运行效率,减少空闲时间,在 CPU 和内存之间会有 cache 层,也就是缓存层的存在。虽然缓存的容量比内存小,但是缓存的速度却比内存的速度要快得多,其中 L1 缓存的速度仅次于寄存器的速度。结构示意图如下所示:在图中,从下往上分别是内存,L3 缓存、L2 缓存、L1 缓存,寄存器,然后最上层是 CPU 的 4个核心。从内存,到 L3 缓存,再到 L2 和 L1 缓存,转载 2021-04-09 14:10:27 · 868 阅读 · 0 评论 -
Java多线程学习三十六:Java内存结构与Java内存模型的区别
本课时我们主要介绍什么是 Java 内存模型?如果你想了解 Java 并发的底层原理,那么 Java 内存模型的知识非常重要,同时也是一个分水岭,可以区分出我们是仅停留在如何使用并发工具,还是能更进一步,知其所以然。VM 内存结构VS Java 内存模型Java 作为一种面向对象的语言,有很多概念,从名称上看起来比较相似,比如 JVM 内存结构、Java 内存模型,这是两个截然不同的概念,但是很容易混淆。网络上也有不少讲 Java 内存模型的文章,其实写的是 JVM 内存结构。所以我们就先.转载 2021-04-08 22:27:03 · 228 阅读 · 0 评论 -
Java多线程学习三十五: CyclicBarrier 和 CountDownLatch 有什么不同
CyclicBarrier 和 CountDownLatch 有什么不同?CyclicBarrier作用CyclicBarrier 和 CountDownLatch 确实有一定的相似性,它们都能阻塞一个或者一组线程,直到某种预定的条件达到之后,这些之前在等待的线程才会统一出发,继续向下执行。正因为它们有这个相似点,你可能会认为它们的作用是完全一样的,其实并不是。CyclicBarrier 可以构造出一个集结点,当某一个线程执行 await() 的时候,它就会到这个集结点开始等待,等待...转载 2021-04-08 21:44:49 · 122 阅读 · 0 评论 -
Java多线程学习三十四:使用 Future 有哪些注意点?Future 产生新的线程了吗
Future 的注意点1. 当 for 循环批量获取 Future 的结果时容易 block,get 方法调用时应使用 timeout 限制对于 Future 而言,第一个注意点就是,当 for 循环批量获取 Future 的结果时容易 block,在调用 get 方法时,应该使用 timeout 来限制。下面我们具体看看这是一个什么情况。首先,假设一共有四个任务需要执行,我们都把它放到线程池中,然后它获取的时候是按照从 1 到 4 的顺序,也就是执行 get() 方法来获取的,代码如.转载 2021-04-08 14:25:41 · 1247 阅读 · 0 评论 -
Java多线程学习三十三:Future 的主要功能是什么?
Future 类Future 的作用Future 最主要的作用是,比如当做一定运算的时候,运算过程可能比较耗时,有时会去查数据库,或是繁重的计算,比如压缩、加密等,在这种情况下,如果我们一直在原地等待方法返回,显然是不明智的,整体程序的运行效率会大大降低。我们可以把运算的过程放到子线程去执行,再通过 Future 去控制子线程执行的计算过程,最后获取到计算结果。这样一来就可以把整个程序的运行效率提高,是一种异步的思想。Callable 和 Future 的关系接下来我们介绍下 Callabl转载 2021-04-07 22:02:31 · 1103 阅读 · 0 评论 -
Java多线程学习三十二:Callable 和 Runnable 的不同?
为什么需要 Callable?Runnable 的缺陷先来看一下,为什么需要 Callable?要想回答这个问题,我们先来看看现有的 Runnable 有哪些缺陷?不能返回一个返回值第一个缺陷,对于 Runnable 而言,它不能返回一个返回值,虽然可以利用其他的一些办法,比如在 Runnable 方法中写入日志文件或者修改某个共享的对象的办法,来达到保存线程执行结果的目的,但这种解决问题的行为千曲百折,属于曲线救国,效率着实不高。实际上,在很多情况下执行一个子线程时,我们都希望能...转载 2021-04-07 21:42:58 · 201 阅读 · 0 评论 -
Java多线程学习三十一:ThreadLocal 是用来解决共享资源的多线程访问的问题吗?
ThreadLocal 是不是用来解决共享资源的多线程访问的。这是一个常见的面试问题,如果被问到了 ThreadLocal,则有可能在你介绍完它的作用、注意点等内容之后,再问你:ThreadLocal 是不是用来解决共享资源的多线程访问的呢?假如遇到了这样的问题,其思路一定要清晰。这里我给出一个参考答案。ThreadLocal 并不是用来解决共享资源问题的。虽然 ThreadLocal 确实可以用于解决多线程情况下的线程安全问题,但其资源并不是共享的,而是每个线程独享的。所以这道题其实是有一定陷阱成转载 2021-04-03 22:59:10 · 271 阅读 · 0 评论 -
Java多线程学习三十:ThreadLocal 适合用在哪些实际生产的场景中
我们在学习一个工具之前,首先应该知道这个工具的作用,能带来哪些好处,而不是一上来就闷头进入工具的 API、用法等,否则就算我们把某个工具的用法学会了,也不知道应该在什么场景下使用。所以,我们先来看看究竟哪些场景下需要用到 ThreadLocal。在通常的业务开发中,ThreadLocal 有两种典型的使用场景。场景1,ThreadLocal 用作保存每个线程独享的对象,为每个线程都创建一个副本,这样每个线程都可以修改自己所拥有的副本, 而不会影响其他线程的副本,确保了线程安全。场景2,Threa转载 2021-04-01 21:44:18 · 204 阅读 · 1 评论 -
Java多线程学习二十九:AtomicInteger(原子类) 和 synchronized 的异同点?
原子类和 synchronized 关键字都可以用来保证线程安全,在本课时中,我们首先分别用原子类和 synchronized 关键字来解决一个经典的线程安全问题,给出具体的代码对比,然后再分析它们背后的区别。代码对比首先,原始的线程不安全的情况的代码如下所示:复制代码public class Lesson42 implements Runnable { static int value = 0; public static void main(String[] args) ...转载 2021-03-27 21:29:49 · 486 阅读 · 0 评论 -
Java多线程学习二十八:原子类和 volatile 有什么异同?
原子类和 volatile 有什么异同案例说明 volatile 和原子类的异同我们首先看一个案例。如图所示,我们有两个线程。在图中左上角可以看出,有一个公共的 boolean flag 标记位,最开始赋值为 true,然后线程 2 会进入一个 while 循环,并且根据这个 flag 也就是标记位的值来决定是否继续执行或着退出。最开始由于 flag 的值是 true,所以首先会在这里执行一定时期的循环。然后假设在某一时刻,线程 1 把这个 flag 的值改为 false 了,它所.转载 2021-03-22 22:11:46 · 375 阅读 · 0 评论 -
Java多线程学习二十七:AtomicInteger 在高并发下性能不好,如何解决?为什么?
AtomicInteger 在高并发下性能不好,如何解决?以及为什么会出现这种情况?我们知道在JDK1.5 中新增了并发情况下使用的 Integer/Long所对应的原子类 AtomicInteger 和 AtomicLong。在并发的场景下,如果我们需要实现计数器,可以利用 AtomicInteger 和 AtomicLong,这样一来,就可以避免加锁和复杂的代码逻辑,有了它们之后,我们只需要执行对应的封装好的方法,例如对这两个变量进行原子的增操作或原子的减操作,就可以满足大部分业务场景...转载 2021-03-21 22:53:33 · 894 阅读 · 0 评论 -
Java多线程学习二十六:原子类是如何利用 CAS 保证线程安全的?
什么是原子类,以及它有什么作用。在编程领域里,原子性意味着“一组操作要么全都操作成功,要么全都失败,不能只操作成功其中的一部分”。而 java.util.concurrent.atomic 下的类,就是具有原子性的类,可以原子性地执行添加、递增、递减等操作。比如之前多线程下的线程不安全的 i++ 问题,到了原子类这里,就可以用功能相同且线程安全的 getAndIncrement 方法来优雅地解决。原子类的作用和锁有类似之处,是为了保证并发情况下线程安全。不过原子类相比于锁,有一定的优势:粒度更细转载 2021-03-20 21:12:58 · 321 阅读 · 0 评论 -
Java多线程学习二十五:阻塞和非阻塞队列的并发安全原理||如何选择适合自己的阻塞队列?
阻塞和非阻塞队列的并发安全原理。之前我们探究了常见的阻塞队列的特点,以 ArrayBlockingQueue 为例,首先分析 BlockingQueue 即阻塞队列的线程安全原理,然后再看看它的兄弟——非阻塞队列的并发安全原理。通过本课时的学习,我们就可以了解到关于并发队列的底层原理了。ArrayBlockingQueue 源码分析我们首先看一下 ArrayBlockingQueue 的源码,ArrayBlockingQueue 有以下几个重要的属性:复制代码//用于存放元素的数组f.转载 2021-03-20 20:34:56 · 257 阅读 · 0 评论 -
Java多线程学习二十四:阻塞队列包含哪些常用的方法?add、offer、put 等方法的区别?
阻塞队列包含哪些常用的方法,以及 add,offer,put 等方法的区别。在阻塞队列中有很多方法,而且它们都非常相似,所以非常有必要对这些类似的方法进行辨析,所以本课时会用分类的方式,和你一起,把阻塞队列中常见的方法进行梳理和讲解。我们把 BlockingQueue 中最常用的和添加、删除相关的 8 个方法列出来,并且把它们分为三组,每组方法都和添加、移除元素相关。这三组方法由于功能很类似,所以比较容易混淆。它们的区别仅在于特殊情况:当队列满了无法添加元素,或者是队列空了无法移除元素时,.转载 2021-03-11 20:35:31 · 723 阅读 · 0 评论 -
Java多线程学习二十三:什么是阻塞队列
阻塞队列的作用阻塞队列,也就是 BlockingQueue,它是一个接口,如代码所示:publicinterfaceBlockingQueue<E>extendsQueue<E>{...}BlockingQueue 继承了 Queue 接口,是队列的一种。Queue 和 BlockingQueue 都是在 Java 5 中加入的。BlockingQueue 是线程安全的,我们在很多场景下都可以利用线程安全的队列来优雅地解决我们业务自身的线程安全问题。比如...转载 2021-03-11 20:20:28 · 157 阅读 · 0 评论 -
Java多线程学习二十二:为什么 Map 桶中超过 8 个才转为红黑树
为什么 Map 的桶中超过 8 个才转为红黑树?JDK1.8 的 HashMap 和 ConcurrentHashMap 都有这样一个特点:最开始的 Map 是空的,因为里面没有任何元素,往里放元素时会计算 hash 值,计算之后,第 1 个 value 会首先占用一个桶(也称为槽点)位置,后续如果经过计算发现需要落到同一个桶中,那么便会使用链表的形式往后延长,俗称“拉链法”,如图所示:图中,有的桶是空的, 比如第 4 个;有的只有一个元素,比如 1、3、6;有的就是刚才说的拉链法,比如第 2.转载 2021-03-07 22:05:41 · 134 阅读 · 0 评论 -
Java多线程学习二十一:ConcurrentHashMap 在 Java7 和 8 有何不同
在 Java8 中,对于 ConcurrentHashMap 这个常用的工具类进行了很大的升级,对比之前 Java7 版本在诸多方面都进行了调整和变化。不过,在 Java7 中的 Segment 的设计思想依然具有参考和学习的价值,所以在很多情况下面试官都会问你:ConcurrentHashMap 在 Java 7 和 Java8 中的结构分别是什么?它们有什么相同点和不同点?所以本课时就对 ConcurrentHashMap 在这两个版本的特点和性质进行对比和介绍。Java 7 版本的 Con...转载 2021-03-07 21:38:01 · 247 阅读 · 0 评论 -
Java多线程学习二十:HashMap 为什么是线程不安全的
为什么 HashMap 是线程不安全的?而对于 HashMap,相信你一定并不陌生,HashMap 是我们平时工作和学习中用得非常非常多的一个容器,也是 Map 最主要的实现类之一,但是它自身并不具备线程安全的特点,可以从多种情况中体现出来,下面我们就对此进行具体的分析。源码分析第一步,我们来看一下 HashMap 中 put 方法的源码:复制代码publicVput(Kkey,Vvalue){if(key==null)returnputForNu...转载 2021-03-05 21:17:00 · 197 阅读 · 0 评论 -
Java多线程学习十九:JVM 对锁进行了哪些优化?
JVM 对锁进行了哪些优化呢?相比于 JDK 1.5,在 JDK 1.6 中 HotSopt 虚拟机对 synchronized 内置锁的性能进行了很多优化,包括自适应的自旋、锁消除、锁粗化、偏向锁、轻量级锁等。有了这些优化措施后,synchronized 锁的性能得到了大幅提高,下面我们分别介绍这些具体的优化。自适应的自旋锁首先,我们来看一下自适应的自旋锁。先来复习一下自旋的概念和自旋的缺点。“自旋”就是不释放 CPU,一直循环尝试获取锁,如下面这段代码所复制代码publicfin..转载 2021-03-04 21:58:25 · 172 阅读 · 1 评论 -
Java多线程学习十八:什么是自旋锁?自旋的好处和后果是什么呢?
什么是自旋锁?以及使用自旋锁的好处和后果分别是什么呢?什么是自旋首先,我们了解什么叫自旋?“自旋”可以理解为“自我旋转”,这里的“旋转”指“循环”,比如 while 循环或者 for 循环。“自旋”就是自己在这里不停地循环,直到目标达成。而不像普通的锁那样,如果获取不到锁就进入阻塞。对比自旋和非自旋的获取锁的流程下面我们用这样一张流程图来对比一下自旋锁和非自旋锁的获取锁的过程。首先,我们来看自旋锁,它并不会放弃 CPU 时间片,而是通过自旋等待锁的释放,也就是说,它会不停地...转载 2021-03-04 21:46:22 · 1126 阅读 · 2 评论 -
Java多线程学习十七:读锁应该插队吗?什么是读写锁的升降级?
读锁应该插队吗?以及什么是读写锁的升降级。读锁插队策略首先,我们来看一下读锁的插队策略,公平与非公平锁中讲到的 ReentrantLock,如果锁被设置为非公平,那么它是可以在前面线程释放锁的瞬间进行插队的,而不需要进行排队。在读写锁这里,策略也是这样的吗?首先,我们看到 ReentrantReadWriteLock 可以设置为公平或者非公平,代码如下:公平锁:ReentrantReadWriteLockreentrantReadWriteLock=newReentrantReadW...转载 2021-03-04 21:32:12 · 197 阅读 · 1 评论 -
Java多线程学习十六:读写锁 ReadWriteLock 获取锁有哪些规则
读写锁 ReadWriteLock 获取锁有哪些规则呢?在没有读写锁之前,我们假设使用普通的 ReentrantLock,那么虽然我们保证了线程安全,但是也浪费了一定的资源,因为如果多个读操作同时进行,其实并没有线程安全问题,我们可以允许让多个读操作并行,以便提高程序效率。但是写操作不是线程安全的,如果多个线程同时写,或者在写的同时进行读操作,便会造成线程安全问题。我们的读写锁就解决了这样的问题,它设定了一套规则,既可以保证多个线程同时读的效率,同时又可以保证有写入操作时的线程安全。整体思路转载 2021-03-02 22:16:42 · 171 阅读 · 0 评论 -
Java多线程学习十五:公平锁和非公平锁,为什么要“非公平”?
什么是公平和非公平公平锁指的是按照线程请求的顺序,来分配锁;非公平锁指的是不完全按照请求的顺序,在一定情况下,可以允许插队。但需要注意这里的非公平并不是指完全的随机,不是说线程可以任意插队,而是仅仅“在合适的时机”插队。那么什么时候是合适的时机呢?假设当前线程在请求获取锁的时候,恰巧前一个持有锁的线程释放了这把锁,那么当前申请锁的线程就可以不顾已经等待的线程而选择立刻插队。但是如果当前线程请求的时候,前一个线程并没有在那一时刻释放锁,那么当前线程还是一样会进入等待队列。为了能够更好的转载 2021-03-01 21:02:05 · 238 阅读 · 0 评论 -
Java多线程学习十四:Lock 有哪几个常用方法?分别有什么用?
Lock 接口是 Java 5 引入的,最常见的实现类是 ReentrantLock,可以起到“锁”的作用。Lock 和 synchronized 是两种最常见的锁,锁是一种工具,用于控制对共享资源的访问,而 Lock 和 synchronized 都可以达到线程安全的目的,但是在使用上和功能上又有较大的不同。所以 Lock 并不是用来代替 synchronized 的,而是当使用 synchronized 不合适或不足以满足要求的时候,Lock 可以用来提供更高级功能的。通常情况下,Lock 只.转载 2021-03-01 20:24:23 · 173 阅读 · 0 评论 -
Java多线程学习十三:synchronized 和 Lock 区别以及孰优孰劣,如何选择?
synchronized 和 Lock 的异同点,以及该如何选择。相同点synchronized 和 Lock 的相同点非常多,我们这里重点讲解 3 个比较大的相同点 ABC。A:synchronized 和 Lock 都是用来保护资源线程安全的。这一点毋庸置疑,这是它们的基本作用。B:都可以保证可见性。对于 synchronized 而言,线程 A 在进入 synchronized 块之前或在 synchronized 块内进行操作,对于后续的获得同一个 monitor 锁.转载 2021-02-28 21:44:14 · 368 阅读 · 0 评论 -
Java多线程学习十二: synchronized的工作原理 以及背后的“monitor 锁”
我们研究下 synchronized 背后的 monitor 锁。获取和释放 monitor 锁的时机我们都知道,最简单的同步方式就是利用 synchronized 关键字来修饰代码块或者修饰一个方法,那么这部分被保护的代码,在同一时刻就最多只有一个线程可以运行,而 synchronized 的背后正是利用 monitor 锁实现的。所以首先我们来看下获取和释放 monitor 锁的时机,每个 Java 对象都可以用作一个实现同步的锁,这个锁也被称为内置锁或 monitor 锁,获得 mon.转载 2021-02-28 21:23:39 · 195 阅读 · 0 评论 -
Java多线程学习十二:悲观锁和乐观锁的本质||
悲观锁和乐观锁是从是否锁住资源的角度进行分类的。悲观锁悲观锁比较悲观,它认为如果不锁住这个资源,别的线程就会来争抢,就会造成数据结果错误,所以悲观锁为了确保结果的正确性,会在每次获取并修改数据时,都把数据锁住,让其他线程无法访问该数据,这样就可以确保数据内容万无一失。这也和我们人类中悲观主义者的性格是一样的,悲观主义者做事情之前总是担惊受怕,所以会严防死守,保证别人不能来碰我的东西,这就是悲观锁名字的含义。乐观锁乐观锁比较乐观,认为自己在操作资源的时候不会有其..转载 2021-02-28 21:01:09 · 120 阅读 · 0 评论 -
Java多线程学习十一:你知道哪几种锁?各有什么特点
锁的 7 大分类需要首先指出的是,这些多种多样的分类,是评价一个事物的多种标准,比如评价一个城市,标准有人口多少、经济发达与否、城市面积大小等。而一个城市可能同时占据多个标准,以北京而言,人口多,经济发达,同时城市面积还很大。同理,对于 Java 中的锁而言,一把锁也有可能同时占有多个标准,符合多种分类,比如 ReentrantLock 既是可中断锁,又是可重入锁。根据分类标准我们把锁分为以下 7 大类别,分别是:偏向锁/轻量级锁/重量级锁;可重入锁/非可重入锁;共...转载 2021-02-28 13:20:10 · 227 阅读 · 0 评论 -
Java多线程学习十:线程池实现“线程复用”的原理
线程复用原理我们知道线程池会使用固定数量或可变数量的线程来执行任务,但无论是固定数量或可变数量的线程,其线程数量都远远小于任务数量,面对这种情况线程池可以通过线程复用让同一个线程去执行不同的任务,那么线程复用背后的原理是什么呢?线程池可以把线程和任务进行解耦,线程归线程,任务归任务,摆脱了之前通过 Thread 创建线程时的一个线程必须对应一个任务的限制。在线程池中,同一个线程可以从 BlockingQueue 中不断提取新任务来执行,其核心原理在于线程池对 Thread 进行了封装,并不是每次执转载 2021-02-26 21:06:04 · 469 阅读 · 0 评论 -
Java多线程学习九:怎样确定线程数量及CPU 核心数和线程数的关系||如何定制自己的线程池
调整线程池中的线程数量的最主要的目的是为了充分并合理地使用 CPU 和内存等资源,从而最大限度地提高程序的性能。在实际工作中,我们需要根据任务类型的不同选择对应的策略。CPU 密集型任务首先,我们来看 CPU 密集型任务,比如加密、解密、压缩、计算等一系列需要大量耗费 CPU 资源的任务。对于这样的任务最佳的线程数为 CPU 核心数的 1~2 倍,如果设置过多的线程数,实际上并不会起到很好的效果。此时假设我们设置的线程数量是 CPU 核心数的 2 倍以上,因为计算任务非常重,会占用大量的 CPU 资源,转载 2021-02-25 20:15:21 · 2818 阅读 · 0 评论 -
Java多线程学习八:线程池常用的阻塞队列
线程池内部结构线程池的内部结构主要由四部分组成,如图所示。第一部分是线程池管理器,它主要负责管理线程池的创建、销毁、添加任务等管理操作,它是整个线程池的管家。第二部分是工作线程,也就是图中的线程 t0~t9,这些线程勤勤恳恳地从任务队列中获取任务并执行。第三部分是任务队列,作为一种缓冲机制,线程池会把当下没有处理的任务放入任务队列中,由于多线程同时从任务队列中获取任务是并发场景,此时就需要任务队列满足线程安全的要求,所以线程池中任务队列采用 BlockingQueue 来保障线程安全。转载 2021-02-25 19:57:35 · 794 阅读 · 0 评论 -
Java多线程学习七:线程池的 4 种拒绝策略和 6 种常见的线程池
以便在必要的时候按照我们的策略来拒绝任务,那么拒绝任务的时机是什么呢?线程池会在以下两种情况下会拒绝新提交的任务。第一种情况是当我们调用 shutdown 等方法关闭线程池后,即便此时可能线程池内部依然有没执行完的任务正在执行,但是由于线程池已经关闭,此时如果再向线程池内提交任务,就会遭到拒绝。第二种情况是线程池没有能力继续处理新提交的任务,也就是工作已经非常饱和的时候。我们具体讲一下第二种情况,也就是由于工作饱和导致的拒绝。比如新建一个线程池,使用容量上限为 10 的 ArrayBlockingQ转载 2021-02-24 20:40:09 · 1019 阅读 · 0 评论 -
Java多线程学习六:使用线程池比手动创建线程好在那里以及常用线程池参数的意义
为什么要使用线程池首先,回顾线程池的相关知识,在 Java 诞生之初是没有线程池的概念的,而是先有线程,随着线程数的不断增加,人们发现需要一个专门的类来管理它们,于是才诞生了线程池。没有线程池的时候,每发布一个任务就需要创建一个新的线程,这样在任务少时是没有问题的,如代码所示。/***描述:单个任务的时候,新建线程来执行*/publicclassOneTask{publicstaticvoidmain(String[]args){...转载 2021-02-23 22:05:51 · 247 阅读 · 0 评论