![](https://img-blog.csdnimg.cn/20201014180756913.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
多线程
文章平均质量分 75
小小大侠客
用技术改变世界,用代码改变命运!
展开
-
细说CountDownLatch
在面试中,当被问及是否使用过CountDownLatch 时,可以结合上述示例和自己的项目经验,详细阐述其应用场景和使用方法,以展示自己在并发编程方面的能力和经验。在实际开发中,有时需要将一个大任务分解成若干个小任务并行处理,待所有小任务完成后,再进行后续处理。例如,在文件处理、数据处理、网络请求等场景中,可以将大文件分割成多个小文件并行处理,或同时向多个服务器发起请求,待所有任务完成后再合并结果。在一些计算密集型任务中,可以将计算任务分解到多个线程中并行处理,待所有线程完成计算后,再汇总结果。原创 2024-06-20 14:19:20 · 371 阅读 · 0 评论 -
Spring Boot的@Async注解有哪些坑需要避免
SpringBoot的@Async注解为异步编程提供了极大的便利,但在使用时必须注意其背后的代理机制和具体实现细节。它可以将标注的方法从调用者的线程中分离出来,另起一个新线程执行,从而避免阻塞调用者的线程,提高系统的并发能力和响应速度。问题:默认情况下,SpringBoot会使用一个简单的SimpleAsyncTaskExecutor,这个执行器不是真正的线程池,可能会导致性能问题。原因:这是因为Spring的代理机制,只有通过代理对象调用时注解才生效,而类内部的自调用不会经过代理对象。原创 2024-06-04 10:11:08 · 869 阅读 · 0 评论 -
Java 的 8 种异步实现方式
如果我们希望一旦计算完成就拿到结果展示给用户或者做另外的计算,就必须使用另一个线程不断的查询计算状态。Future件彼此孤立:有时某一个耗时很长的异步任务执行结束之后,你想利用它返回的结果再做进一步的运算,该运算也会是一个异步任务,两者之间的关系需要程序开发人员手动进行绑定赋予,Future并不能将其形成一个任务流(pipeline),每一个Future都是彼此之间都是孤立的,所以才有了后面的CompletableFuture,CompletableFuture就可以将多个Future串联起来形成任务流。原创 2024-02-19 14:22:40 · 963 阅读 · 0 评论 -
多线程并发之线程通信
场景:当你有很大一个List的时候,有时候业务处理时就需要将List拆分处理,比如你调用依赖方接口,Get请求中包含这个超长的List入参,这样请求URL就会出现过长的问题,所以可以使用Lists.partition进行分割。结合Semaphore是为了控制并发量,以防依赖方接口不能支撑住很大并发量,使用Semaphore控制并发量以保证不给依赖方接口打死。多个线程并发执行时,在默认情况下CPU是随机切换线程的,有时我们希望CPU按我们的规律执行线程,此时就需要线程之间协调通信。原创 2023-07-10 16:32:24 · 134 阅读 · 0 评论 -
Java内置线程池ExecutorService介绍及商品秒杀案例
第一、ExecutorService接口是java内置的线程池接口,通过学习接口中的方法,可以快速的掌握java内置线程池的基本使用常用方法:void shutdown() 启动一次顺序关闭,执行以前提交的任务,但不接受新任务。List shutdownNow() 停止所有正在执行的任务,暂停处理正在等待的任务,并返回等待执行的任务列表。 Future submit(Callable task) 执行带返回值的任务,返回一个Future对象。Future<?> submit(Ru原创 2022-05-14 19:52:19 · 834 阅读 · 0 评论 -
自定义线程池
第一、什么是线程池线程池其实就是一种多线程处理形式,处理过程中可以将任务添加到队里中,然后在创建线程后自动启动这些任务。这里的任务就是实现了Runnable或Callable接口的实例对象。第二、为什么使用线程池使用线程池最大的原因就是可以根据系统的需求和硬件环境灵活的控制线程的数量,且可以对所有线程进行统一的管理和控制,从而提高系统的运行效率,降低系统运行压力;第三、使用线程池有哪些优势a.线程和任务分离,提升线程重用性b.控制线程并发数量,降低服务器压力,统一管理所有线程c.提升系统响应速原创 2022-05-08 21:02:32 · 955 阅读 · 0 评论 -
探究ThreadLocal内存泄漏及弱引用
第一、前言有些程序员在使用ThreadLocal的过程中会发现有内存泄漏的情况,就猜测这个内存泄漏与Entry中使用了弱引用的key有关系。第二、内存泄漏的相关概念1.Memory overflow:内存溢出是没有足够的内存提供申请者使用。2.Memory leak:内存泄漏是指程序中已动态分配的内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃的严重后果。内存泄漏的堆积终将导致内存溢出。第三、弱引用的相关概念Java中的引用有4种类型:强、软、弱、虚。当原创 2020-08-02 21:23:24 · 937 阅读 · 0 评论 -
ThreadLocalMap线性探测法解决hash冲突
第一、前言ThreadLocal使用的是自定义的ThreadLocalMap,接下来我们来探究一下ThreadLocalMap的hash冲突解决方式。第二、ThreadLocal的set()方法public void set(T value) { Thread t = Thread.currentThread(); ThreadLocal.ThreadLocalMap map = getMap(t); if (map != null) map.set(this,原创 2020-08-01 17:20:33 · 5557 阅读 · 0 评论 -
ThreadLocal无锁化线程封闭及与Synchronized的区别
第一、前言建议将本文和ThreadLocal应用场景-事务案例一起阅读。第二、ThreadLocal简介从Java官方文档中的描述:ThreadLocal类用来提供线程内部的局部变量。这种变量在多线程环境下访问(通过get和set方法访问)时能保证各个线程的变量相对独立于其他线程内的变量。ThreadLocal实例通常来说都是private static类型的,用于关联线程和线程上下文。总结:1.线程并发:在多线程并发的场景下2.传递数据:我们可以通过ThreadLocal在同一线程,不同组件中原创 2020-07-25 10:48:08 · 189 阅读 · 0 评论 -
ThreadLocal的核心方法源码
第一、前言基于ThreadLocal的内部结构,我们继续探究一下ThreadLocal的核心方法源码,更深入的了解其操作原理。除了构造之外, ThreadLocal对外暴露的方法有以下4个:第二、get方法1、源码和对应的中文注释 /** * 返回当前线程中保存ThreadLocal的值 * 如果当前线程没有此ThreadLocal变量,则它会通过调用{@link #initialValue} 方法进行初始化值 * @return 返回当前线程对应此Thread原创 2020-07-19 21:16:33 · 154 阅读 · 0 评论 -
ThreadLocal内部结构探究实现线程数据隔离的原理
第一、前言本篇文章主要通过分析ThreadLocal的内部结构,探究它能够实现线程数据隔离的原理。第二、JDK早期设计每个ThreadLocal都创建一个Map,然后用线程作为Map的Key,要存储的局部变量作为Map的value,这样就能达到各个线程的局部变量隔离的效果。第三、JDK8的设计每个Thread维护一个ThreadLocalMap,这个Map的key是ThreadLocal实例本身,value才是真正要存储的值Object。具体的过程是这样的:1、每个Thread线程内部都有一原创 2020-07-19 20:54:51 · 580 阅读 · 1 评论 -
ThreadLocal应用场景-事务案例
第一、ThreadLocal介绍1.线程并发: 在多线程并发的场景下2.传递数据: 我们可以通过ThreadLocal在同一线程,不同组件中传递公共变量3.线程隔离: 每个线程的变量都是独立的,不会相互影响第二、常用方法第三、事务案例1、场景构建这里我们先构建一个简单的转账场景: 有一个数据表account,里面有两个用户Jack和Rose,用户Jack 给用户Rose 转账。 案例的实现就简单的用mysql数据库,JDBC 和 C3P0 框架实现。2、数据准备,新建表t_account,原创 2020-07-18 18:25:58 · 519 阅读 · 0 评论 -
通过javap反汇编学习synchronized的原理
编写简单的同步代码块public class Demo{ private static Object obj=new Object(); public static void main(String [] args){ synchronized(obj){ System.out.println("HelloWorld"); } }}我们要看synchroni...原创 2020-03-29 21:23:01 · 339 阅读 · 0 评论 -
并发编程之Synchronized与Lock的区别
第一、synchronized的特性1、可重入特性一个线程可以多次执行synchronized重复获取同一把锁。2、代码演示/** * 演示synchronized可重入 * 1.自定义一个线程类;2.在线程类的run方法中使用嵌套的同步代码块;3.使用两个线程来执行 * @author shixiangcheng * 2020-03-28 */public class Dem...原创 2020-03-28 22:51:03 · 164 阅读 · 0 评论 -
伪共享问题-并发编程无声的性能杀手
本文以LongAdder源码为例进行说明。关于原子累加器的论述可以参考文章:原子累加器LongAdder与AtomicLong1.LongAdder部分源码2.多核机器的存储结构CPU为了提升性能,在设计上都设计了多级缓存。一个CPU会分多个核心,每个CPU核心都有自己的一级缓存、二级缓存,多个核心之间可以共享三级缓存,多个CPU之间可以共享内存。时间对比3.伪共享问题因为CPU与...原创 2020-01-12 16:35:55 · 308 阅读 · 0 评论 -
在不加锁的情况下,实现一个线程安全的单例模式
第一、单例模式的几种实现方式a.饿汉式(线程安全,调用效率高,但是不能延时加载)/** * 单例模式 * @author shixiangcheng * 2019-07-21 */public class Singleton { private static final Singleton singleton=new Singleton(); private Sing...原创 2019-12-20 10:31:03 · 947 阅读 · 0 评论 -
原子累加器LongAdder与AtomicLong
1.在Java8中,Doug Lea大师在java.util.concurrent.atomic包中添加了几个新的类,其中有一个是LongAdder。2.如下代码,对比LongAdder和AtomicLong的性能import java.util.ArrayList;import java.util.List;import java.util.concurrent.atomic.Atomi...原创 2019-12-20 09:50:45 · 579 阅读 · 0 评论 -
原子引用与ABA问题
第一、常用的原子引用类JUC开发包提供了:AtomicReference:是对”对象”进行原子操作。AtomicMarkableReference:不关心引用变量更改了几次,只是单纯关心是否更改过。AtomicStampedReference:可以给引用加上版本号,追踪引用的整个变化过程,可以知道引用变量中途被更改了几次。原子引用提供了一种读和写都是原子性的对象引用变量。原子意味着多个线...原创 2019-12-17 15:22:50 · 567 阅读 · 0 评论 -
并发编程CAS与Volatile
第一、并发编程三大特性原子性:指一系列操作是不可分割的,一旦执行则整个过程将会一次性全部执行完成,不会停留在中间状态。(有点类似于事务的概念)。举例:例如A向B汇款1000元,那么就需要有两个操作,一个是A账户减1000元,另一个是B账户增加1000元,如果这个过程中任何一个操作出现故障,都是不符合规矩的也是不能保障汇款人和收款人的财产安全。换句话说,如果想要保证每次转账都不会造成双方任何一方...原创 2019-12-17 14:34:40 · 182 阅读 · 0 评论 -
Java多线程中的join()方法
1.Thread中的join()join()把指定的线程加入到当前线程,可以将两个交替执行的线程合并为顺序执行的线程。比如在线程B中调用了线程A的Join()方法,直到线程A执行完毕后,才会继续执行线程B。t.join(); //使调用线程 t 在此之前执行完毕。t.join(1000); //等待 t 线程,等待时间是1000毫秒2.为什么要用join()方法主线程生成并...原创 2019-12-06 14:09:51 · 367 阅读 · 0 评论 -
线程安全之ThreadLocal
1.ThreadLocal是一个为线程提供线程局部变量的工具类。就是为线程提供一个线程私有的变量副本,这样多个线程就可以随意更改自己线程局部的变量,不会影响到其它线程。ThreadLocal提供的只是一个浅拷贝,如果变量是一个引用类型,那么就要考虑它内部的状态是否会被改变,要解决这个问题可以通过重写ThreadLocal的initialValue()函数来自己实现深拷贝,建议在使用ThreadLo...原创 2019-06-16 17:18:01 · 413 阅读 · 0 评论 -
并发编程之并发类容器
一、锁对象的改变问题/** * 锁对象的改变问题 * @author shixiangcheng * 2019-06-30 */public class ChangeLock { //锁对象 private String lock="lock"; private void method(){ synchronized(lock){ System.out.println(...原创 2019-07-08 22:15:19 · 104 阅读 · 0 评论 -
多线程之线程之间的通信
一、线程通信的概念线程是操作系统中独立的个体,但这些个体如果不经过特殊的处理就不能成为一个整体,线程间的通信就成为整体的必用方式之一。当线程存在通信指挥,系统间的交互性会更强大,在提高CPU利用率的同时还会使开发人员对线程任务在处理的过程中进行有效地把控与监督。二、线程通信的实现方式使用wait/notify方法实现线程间的通信。(这两个方法都是object类的方法,即java所有的对象都提...原创 2019-06-29 23:11:43 · 335 阅读 · 0 评论 -
并发编程之模拟阻塞Queue
一、使用wait/notify模拟QueueBlockingQueue:首先它是一个队列,并且支持阻塞机制,阻塞的放入和得到数据。我们要实现LinkedBlockingQueue下面两个简单的方法put和take。put(Object):把object加到BlockingQueue里,如果BlockingQueue没有空间,则调用此方法的线程被阻断,直到BlockingQueue里面有空间再继...原创 2019-06-30 17:42:32 · 159 阅读 · 0 评论 -
多线程之Master-Worker模式
Master-Worker模式Master-Worker模式是常用的并行计算模式。它的核心实现是系统由两类进程协作工作:Master进程和Worker进程。Master负责接收和分配任务,Worker负责处理子任务。当各个Worker子进程处理完成后,会将结果返回给Master,由Master做归纳和总结。其好处是能将一个大任务分解成若干个小任务,并行执行,从而提高系统的吞吐量。代码示例任...原创 2019-08-03 23:22:36 · 312 阅读 · 0 评论 -
并发编程之Future模式
1.Future模式和多线程技术密切相关,可以说是利用多线程技术优化程序的一个实例。Future模式的核心在于使用多线程技术去除了主函数中的等待时间,并使得原来需要等待的时间段可以用于处理其他的业务逻辑,从而充分利用计算机资源。2.Future模式是多线程开发中常见的设计模式,它的核心思想是异步调用。对于Future模式来说,它无法立即返回你需要的数据,但是它会返回一个契约,将来你可以凭借这个...原创 2019-08-12 14:31:12 · 179 阅读 · 0 评论 -
线程安全与线程不安全
1.关于线程安全的定义。a.线程安全是当多个线程访问某一个类(对象或方法)时,这个类始终都能表现出正确的行为,那么这个类(对象或方法)就是线程安全的。b.在一个进程中有多个线程并发执行,每个线程执行过程中,变量值是相同的,执行结果也是相同的。2.多个线程访问同一个对象的方法,没有加锁,线程不安全synchronized:可以在任意对象及方法上加锁,而加锁的这段代码称为互斥区或临界区。...原创 2019-05-26 17:00:00 · 245 阅读 · 0 评论