多线程
多线程 学习笔记
ljt-tiger
不积跬步,无以至千里。知识认知体系搭建过程:场景 --》需求 --》解决方案 --》应用 --》原理
展开
-
多线程事物回滚
在spring中 **@Transactional** 注解可以控制事务,使出现异常时会进行回滚。但在**多线程**中则不生效。例如现在需要插入大量业务数据,但在插入数据之前**主线程先执行删除动作**,之后再将数据**等分分批交由子线程去执行**。那么当其中某个子线程执行失败时,主线程删除的数据则不会回滚,从而导致数据一致性受损。因此需要一个解决方案,如下:原创 2023-01-09 21:25:13 · 948 阅读 · 0 评论 -
线程池学习笔记
有一次,我们系统里后台任务线程池的队列和线程池全满了,不断抛出抛弃任 务的异常,通过排查发现是数据库出现了问题,导致执行SQL变得非常缓慢,因为后台任务线 程池里的任务全是需要向数据库查询和插入数据的,所以导致线程池里的工作线程全部阻 塞,任务积压在线程池里。该方法返回一个固定数量的线程池,当有一个任务提交时,若线程池中空闲,则立即执行,若没有,则会被暂缓在一个任务队列中,等待有空闲的线程去执行,用途:FixedThreadPool 用于负载比较大的服务器,为了资源的合理利用,需要限制当前线程数量。原创 2022-10-08 23:21:24 · 167 阅读 · 0 评论 -
ThreadMXBean
ThreadMXBean,一个查看java进程中线程信息的类,由工厂类ManagementFactory创建原创 2022-10-07 11:54:35 · 484 阅读 · 0 评论 -
CountDownLatch
CountDownLatch使用场景涉及到需要指定某个事物在执行之前,要等到前置人物执行完毕之后才执行特点允许一个或多个线程一直等待,直到其他线程的操作执行完毕再执行。从命名可以解读到 countdown 是倒数的意思,类似于我们倒计时的概念。countdownlatch 提供了两个方法,一个是 countDown,一个是 await,countdownlatch 初始化的时候需要传入一个整数,在这个整数倒数到 0 之前,调用了 await 方法的程序都必须要等待,然后通过 countDown原创 2022-03-13 22:36:51 · 513 阅读 · 0 评论 -
线程池-ThreadPoolExecutor
线程池-ThreadPoolExecutor使用场景想要频繁的创建和销毁线程的时候线程池的概念线程池就是提前创建若干个线程,如果有任务需要处理,线程池里的线程就会处理任务,处理完之后线程并不会被销毁,而是等待下一个任务。由于创建和销毁线程都是消耗系统资源的线程池的优势降低创建线程和销毁线程的性能开销提高响应速度,当有新任务需要执行是不需要等待线程创建就可以立马执行合理的设置线程池大小(限流)可以避免因为线程数超过硬件资源瓶颈带来的问题Api ExecutorsnewFixedTh原创 2021-07-03 20:49:22 · 127 阅读 · 0 评论 -
BlockingQueue
BlockingQueue堵塞队列,有两种情况会堵塞队列满时,入队线程会被堵塞队列空时,出对线程会被堵塞操作Throws ExceptionSpecial ValueBlocksTimes Out添加add(o)offer(o)put(o)offer(0,timeout,timeunit)移除remove(o)poll()take()poll(timeout,timeunit)检查element()peek()...原创 2021-07-03 10:01:55 · 206 阅读 · 0 评论 -
Fork/Join
Fork/Join用于并行执行任务,将大任务分割成若干个小任务,最终汇总每个小任务结果后得到大任务结果的框架。使用工作窃取算法,某个线程从其他队列里窃取任务来执行fork:将大任务切割成若干个子任务并行执行join:合并子任务的执行结果得到大任务的结果…局限性不能执行I/O操作(读写数据文件)不能抛出检查异常,必须通过必要的代码来处理他们任务只能使用fork和join操作来作为同步机制,如果使用其他同步机制,那么执行任务时,工作线程就不能执行其他任务import lombok.e原创 2021-07-03 09:36:01 · 128 阅读 · 0 评论 -
FutureTask
FutureTask多线程执行任务时,有比较耗时操作,但又需要其返回结果时,可以使用FutureTaskpublic class FutureTaskDemo { public static void main(String[] args) throws Exception { FutureTask<String> futureTask = new FutureTask<String>(() -> { log.info("d原创 2021-07-03 09:35:01 · 143 阅读 · 0 评论 -
Condition
Condition多线程协调调度的工具public class LockExample6 { public static void main(String[] args) { ReentrantLock reentrantLock = new ReentrantLock(); Condition condition = reentrantLock.newCondition(); new Thread(() -> {原创 2021-06-27 10:57:33 · 102 阅读 · 0 评论 -
Lock 锁
ReentrantLock大部分情况下可以使用 synchronized,性能上并无太大差别,使用ReentrantLock要特别注意在finally中释放锁,不然容易出现死锁。特性可指定公平和非公平锁提供Condition类,可分组唤醒需要唤醒的线程提供能够中断等待锁的线程自旋,避免锁进入内核态…public class LockExample2 { // 请求总数 public static int clientTotal = 5000; // 同时并发执行的原创 2021-06-26 13:37:20 · 135 阅读 · 0 评论 -
CyclicBarrier,线程屏障
CyclicBarrier使用场景:【当存在需要一组子任务都完成时,才执行主任务】CyclicBarrier:让一组线程到达一个屏障(也可以叫同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续工作。CyclicBarrier 默认的构造方法是 CyclicBarrier(int parties),其参数表示屏障拦截的线程数量,每个线程调用 await 方法告诉 CyclicBarrier 当前线程已经到达了屏障,然后当前线程被阻塞。…import lombo原创 2021-06-26 10:23:05 · 193 阅读 · 0 评论 -
Semaphore,信号量,限流操作
Semaphore使用场景:【限流操作】,限制某个资源同时被访问的个数semaphore 也就是我们常说的信号灯,semaphore 可以控制同时访问的线程个数,通过 acquire 获取一个许可,如果没有就等待,通过 release 释放一个许可。…import lombok.extern.slf4j.Slf4j;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import原创 2021-06-26 10:00:21 · 308 阅读 · 0 评论 -
线程封闭的几种方式
线程封闭的几种方式Ad-hoc 线程封闭程序控制实现,很糟糕,可以忽略堆栈封闭局部变量,无并发问题ThreadLocal很好的封闭方法原创 2021-06-15 23:48:39 · 171 阅读 · 0 评论 -
ThreadLocal
ThreadLocalpublic class RequestHolder { private final static ThreadLocal<Long> requestHolder = new ThreadLocal<>(); public static void add(Long id) { // 请求到后端服务器,接口处理之前, // 将当前用户信息保存进 ThreadLocal // 一般使用filter原创 2021-06-15 23:43:29 · 95 阅读 · 0 评论 -
几种单例模式
几种单例模式枚举可以天然防止反射和反序列化漏洞 需要延时加载时:枚举好于饿汉式 ,不需要延时加载:静态内部类好于懒汉式 也就是说优先选用 枚举和静态内部类饿汉/** * 饿汉式单例设计模式 * 特点:线程安全、调用效率高、资源利用率低(无懒加载)。 * * @author tiger * @Date 2017年9月2日 */public class SingletonHungry { // 私有构造函数 private SingletonHungry() { }原创 2021-06-14 23:47:24 · 85 阅读 · 1 评论 -
volatile使用场景-标志位
volatile使用场景标志位volatile boolean inited = false;// 线程1String context = loadContext();// 线程2while(!inited){ sleep();}doSomethingWithConfig(context);原创 2021-06-14 17:08:25 · 175 阅读 · 0 评论 -
CAS使用理解
当前内存值(V)、预期原来的值(E)、期待更新的值(N)原创 2021-06-14 17:02:20 · 360 阅读 · 0 评论 -
模拟高并发测试的几种方式
Postman下载软件包# 官网启动测试案例创建一个Collections,将接口保存进Collections点击Runner,选择需要并发测试的接口设置相关参数,点击Run。Apache Bench下载软件包# 官网https://www.apachelounge.com/# 软件包https://www.apachelounge.com/download/VS16/binaries/httpd-2.4.48-win64-VS16.zip启动在目录【xxx\Apac原创 2021-06-14 14:35:21 · 5486 阅读 · 0 评论 -
JMM (JAVA内存模型)
JMM (JAVA内存模型)内存屏障、重排序这些东西好像是和平台以及硬件架构有关系的。作为 Java 语言的特性,一次编写多处运行。我们不应该考虑平台相关的问题,并且这些所谓的内存屏障也不应该让程序员来关心JMM 全称是 Java Memory Model. 什么是 JMM 呢?通过前面的分析发现,导致可见性问题的根本原因是缓存以及重排序。 而 JMM 实际上就是提供了合理的禁用缓存以及禁止重排序的方法。所以它最核心的价值在于解决可见性和有序性JMM 属于语言级别的抽象内存模型,可以简单理解为对硬件原创 2021-05-30 18:13:17 · 141 阅读 · 1 评论 -
Happens - Before 规则
Happens - Before 规则表示的是前一个操作的结果对于后续操作是可见的,表达多个线程之间对于内存的可见性;告诉开发者哪些场景下会存在可见性问题,因为并不是所有的程序指令都会存在可见性和指令重排序问题。程序顺序规则一个线程中的每个操作,happens-before 于该线程中的任意后续操作; 可以简单认为是 as-if-serial,不管程序如何重排序,单线程的执行结果一定不会发生变化。volatile 变量规则对于 volatile 修饰的变量的写的操作,一定 happen-b原创 2021-05-30 17:58:24 · 111 阅读 · 0 评论 -
查看运行代码的汇编指令的工具
将hsdis-amd64.dll和hsdis-amd64.lib文件,复制到JRE_HOME/bin/server路径下在运行main函数之前,加入虚拟机参数// *CLassLayoutDemo.getInstance 替换成实际运行的代码-server -Xcomp -XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly -XX:CompileCommand=compileonly,*CLassLayoutDemo.getInstance...原创 2021-05-30 16:28:02 · 156 阅读 · 0 评论 -
synchronized(锁的升级过程)
synchronized可以解决【原子性、有序性、可见性问题、[对象逃逸]】,也就是解决了线程安全问题线程安全概念:在拥有共享数据的多条线程并行执行的程序中,线程安全的代码会通过同步机制保证各个线程都可以正常且正确的执行,不会出现数据污染等意外情况。本质是管理对数据状态的访问数据是共享的,在线程生命周期里是变化的锁的状态假如有两个线程 ThreadA 和 ThreadB只有线程 ThreadA 去访问(如果这种情况属于大部分情况时)–》偏向锁ThreadA 和 ThreadB原创 2021-05-30 16:02:21 · 124 阅读 · 0 评论 -
对齐填充的目的
概念cup一次读取的数据是缓存行,按块(x86架构64位计算机中是64字节)进行读取,也就是说缓存行是CUP与内存交互的最小工作单元没有对齐填充时,A线程只想要读取一个long类型的变量a,但a只占8字节,因此会连带变量b、c、d也会一并读取到缓存行中;而同一时刻B线程只想要读取一个long类型的变量b,但b只占8字节,因此会连带变量a、c、d也会一并读取到缓存行中;那么这种情况下就会存在伪共享问题,这会导致A和B线程在进行数据操作时会频繁地直接去内存获取最新值,而不是从高速缓存中获取(也就是缓存失效)原创 2021-05-30 11:16:51 · 984 阅读 · 3 评论 -
线程的状态(生命周期)
线程认识进程(Process):是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。在早期面向进程设计的计算机结构中,进程是程序的基本执行实体;在当代面向线程设计的计算机结构中,进程是线程的容器。程序是指令、数据及其组织形式的描述,进程是程序的实体。线程的引入:60年代,在OS中能拥有资源和独立运行的基本单位是进程,然而随着计算机技术的发展,进程出现了很多弊端,一是由于进程是资源拥有者,创建、撤消与切换存在较大的时空开销,因此需要引入轻型进程;二是由原创 2021-05-30 08:58:27 · 80 阅读 · 1 评论 -
在idea中线程断点调试
idea多线程调试原创 2020-08-16 12:06:38 · 1229 阅读 · 0 评论 -
经典的生产者与消费者模型(基于BlockingQueue队列实现)
基于BlockingQueue实现与之前的基于synchronized方法实现的不同,这里不需要单独创建仓库类,用队列替代仓库,简化编程。原创 2017-07-31 08:46:02 · 441 阅读 · 0 评论 -
死锁代码演示
同步代码块内再嵌套一个同步代码块。原创 2017-08-02 19:01:44 · 423 阅读 · 0 评论 -
synchronized 关键字的理解
1、 要保护这一段代码, 必须将它变为临界区,使用Java提供我们的锁机制(同步监视控制)2、在同一个服务线程中(不管是不是同一个任务执行体),这里形象比喻Person(线程)上Toilet(临界区),一次且只能有一个人在Toilet里,只要Person不出来(不释放锁),其他人(其他线程)就不能进入。 3、简单来说就是:两个人不能在一时刻拥有房间的使用权。原创 2017-07-28 19:58:37 · 209 阅读 · 0 评论 -
重入锁--ReentrantLock
优势:当许多线程都在争用同一个锁时,使用 ReentrantLock 的总体开支通常要比 synchronized 少得多,同时具有很多 synchronized 没有的新特性。劣势:需要谨记在finally块中释放锁,上几把就解几次。新手很容易忘记,而synchronized不需要手动解锁。【ReentrantLock不是内建锁】,发生异常不会自动释放锁。在ReentrantLock前加final原创 2017-07-29 09:06:22 · 235 阅读 · 0 评论 -
经典的生产者与消费者模型(基于synchronized方法实现)
注意代码中的生产货物和销售货物的方法要进行同步管理,如下面1、public synchronized void producer(int id,String name){}2、public synchronized void sale(String name){}原创 2017-07-28 09:03:02 · 602 阅读 · 0 评论 -
模拟银行转账信息
从本地 data.txt 文本中读取账户信息,模拟银行不同账户之间的转账信息原创 2017-07-26 23:10:13 · 2955 阅读 · 0 评论