并发编程
文章平均质量分 91
学习多线程
sco5282
这个作者很懒,什么都没留下…
展开
-
【Thread】JAVA 实现主线程等待子线程执行完毕后再执行
工作总往往会遇到异步去执行某段逻辑, 然后先处理其他事情, 处理完后再把那段逻辑的处理结果进行汇总的场景, 这时候就需要使用线程了.一个线程启动之后, 是异步的去执行需要执行的内容的, 不会影响主线程的流程, 往往需要让主线程指定后, 等待子线程的完成。并且,主线程是要利用到子线程的返回数据进行处理。这里有2种方式:实现 Callable 接口、join() 方法1、实现 Callable 接口class SubThread implements Callable<Integer> {原创 2021-11-06 23:30:02 · 2015 阅读 · 0 评论 -
【Thread】并行多线程任务的创建
对于简单的并行任务,可以通过线程池+Future的方案来 解决;如果任务之间有聚合关系,无论是 AND 聚合还是 OR 聚合,都可以通过CompletableFuture来解决;而批量的并行任务,则可以通过CompletionService来解决1. 线程池 + Futurepublic class ExampleTwo { public static void main(String[] args) throws Exception { System.out.println(原创 2021-11-07 15:45:31 · 443 阅读 · 0 评论 -
【Thread】线程池的 7 种创建方式及自定义线程池
1. 什么是线程池线程池(ThreadPool)是一种基于池化思想管理和使用线程的机制。它是将多个线程预先存储在一个“池子”内,当有任务出现时可以避免重新创建和销毁线程所带来性能开销,只需要从“池子”内取出相应的线程执行对应的任务即可。使用线程池主要有以下优点:降低资源消耗提高响应速度提高线程的可管理性同时,阿里巴巴在其《Java开发手册》中也强制规定:线程资源必须通过线程池提供,不允许在应用中自行显式创建线程。2. 使用线程池线程池的创建方法总共有 7 种,但总体来说可分为 2 类:原创 2021-11-06 23:34:30 · 25744 阅读 · 2 评论 -
十一:深入理解 Semaphore —— 信号量
不管线程 D 有没有进入阻塞队列【如果没有进入,那么此时,线程 D 和 线程 C 竞争许可证】,这里假设是线程 C 获取许可证成功,没有多余的许可证(propagate = 0),那么线程 D 就会进入到同步队列【此时,有可能阻塞(线程C.waitStatus = -1),也有可能没阻塞(线程C.waitStatus = 0)】:将当前线程封装为【共享模式】节点入同步队列,再自旋,如果当前节点前驱是 head 节点,再次获取许可证,如果返回结果 >= 0,则表示获取许可证成功,则调用。原创 2024-04-20 11:47:16 · 990 阅读 · 0 评论 -
十:深入理解 CyclicBarrier—— 栅栏锁
让一组线程到达某个屏障,被阻塞,一直到组内的最后一个线程到达,然后屏障开放,接着,所有的线程继续运行是通过独占锁实现的,底层包含了 “ReentrantLock 对象 lock” 和 “Condition 对象 trip”,通过条件队列 trip 来对线程进行阻塞的,并且其内部维护了两个 int 型的变量 parties 和 count。原创 2024-04-18 17:05:22 · 563 阅读 · 0 评论 -
九:深入理解 CountDownLatch —— 闭锁/倒计时锁
通过构造方法初始化:设置 AQS 中的 state 的值调用方法:调用 AQS 的释放同步状态的方法,每调用一次,state 就自减 1,直至为 0调用await()方法:如果 state 不为 0,则阻塞线程并入队列。当 state 为 0 后,唤醒其它所有阻塞的线程。原创 2024-04-18 14:24:29 · 1159 阅读 · 0 评论 -
八:深入理解 Condition —— 线程通信(等待/通知)
当一个持有锁的线程调用将当前线程加入到条件等待队列中,状态为【CONDITION】彻底释放锁,并唤醒同步队列中阻塞的一个线程判断自己是否在同步等待队列中,如果不在,将自己阻塞起来如果被signal()方法唤醒了,则去竞争同步锁当一个持有锁的线程调用删除条件等待节点的头节点将头节点添加到同步等待队列的 tail 之后,如果添加成功,则退出循环;否则,如果条件等待队列中还有节点,则后移,循环步骤 1、2修改头结点的状态【CONDITION => 0】原创 2024-04-16 16:37:01 · 1116 阅读 · 0 评论 -
七:深入理解 ReentrantReadWriteLock —— 读写锁
`ReentrantReadWriteLock`:读写锁。它表示两个锁,一个是读操作相关的锁,称为共享锁;一个是写相关的锁,称为排他锁。适用于**读多写少**的场景(如果用独占锁,效率及其低下),提高并发性能,但也需要更多的内存和处理器时间来维护状态信息原创 2024-04-15 14:22:52 · 722 阅读 · 0 评论 -
六:深入理解 ReentrantLock —— 可重入锁
在文章中,我们介绍了 AQS 的基本原理。是我们比较常用的一种锁,也是基于 AQS 实现的。所以,接下来我们就来分析一下锁的实现。原创 2024-04-13 11:46:03 · 801 阅读 · 0 评论 -
五:深入理解 AbstractQueuedSynchronizer
抽象队列同步器,定义了一套多线程访问共享资源的同步器框架(同步:线程之间的通信、协作),许多同步类实现都依赖于它,如:Lock 包中的各种锁()、concurrent包中的各种同步器(如Semaphore),还有阻塞队列和线程池的实现都有使用到 AQS实现原理:在多线程访问共享资源时,若标识的共享资源【state】空闲,则将当前获取到共享资源的线程设置为有效工作线程,共享资源设置为锁定状态(独占模式下),其他线程没有获取到资源的线程进入阻塞队列【CLH】,等待当前线程释放资源后,继续尝试获取。原创 2024-04-12 11:54:10 · 875 阅读 · 1 评论 -
四:深入理解 volatile 关键字
volatile 变量,保证新值能立即同步回主内存,以及每次使用前立即从主内存刷新,所以我们说volatile保证了多线程操作变量的可见性原创 2024-04-11 15:57:04 · 628 阅读 · 0 评论 -
三:深入理解 synchronized 关键字
count = 0;_waiters = 0,//等待线程数//重入次数//持有锁的线程(逻辑上,实际上除了THREAD,还可能是Lock Record)//线程wait之后会进入该列表//等待获取锁的线程列表,和_EntryList配合使用//等待获取锁的线程列表,和_cxq配合使用//当前持有者是否为THREAD类型,如果是轻量级锁膨胀而来,还没有enter的话,//_owner存储的可能会是Lock Record当多个线程同时访问一段同步代码时,首先会进入。原创 2024-04-09 20:42:20 · 734 阅读 · 0 评论 -
二:深入理解 JAVA 内存模型 JMM
上述问题是因硬件的不断升级导致的。那么,有没有什么机制可以很好的解决上面的这些问题呢?——内存模型为了保证共享内存的正确性(可见性、有序性、原子性),内存模型定义了共享内存系统中多线程程序读写操作行为的规范。通过这些规则来规范对内存的读写操作,从而保证指令执行的正确性【与处理器/缓存/并发/编译器有关】。它解决了 CPU 多级缓存、处理器优化、指令重排等导致的内存访问问题,保证了并发场景下的一致性、原子性和有序性。限制处理器优化和使用内存屏障同一套内存模型规范,不同语言在实现上可能会有些差别。原创 2024-04-09 12:02:42 · 762 阅读 · 0 评论 -
一:深入理解线程 Thread
先了解一下基本概念1. 程序、进程、线程程序、进程、线程程序(静态):为完成特定的任务,用某种语言编写的一组指令的集合。即:一段静态的代码进程(动态):程序的一次执行的过程,或者是正在执行的一个程序。它是一个动态的过程,它有自己的生命周期:产生、存在、消亡。如:运行中的 QQ进程作为资源分配的单位,系统在运行时会为每个进行分配不同的内存区域线程:进程可进一步细化为线程,是一个程序内部的一条执行路径多线程:若一个进程同一时间并行执行多个线程,则是支持多线程的线程作为调度和执行的单位,原创 2021-10-25 20:48:47 · 2241 阅读 · 1 评论