![](https://img-blog.csdnimg.cn/20201014180756928.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
并发编程
文章平均质量分 89
Men-DD
这个作者很懒,什么都没留下…
展开
-
并发编程之深入理解十四:Disruptor
并发编程之深入理解十二:DisruptorDisruptor主要是用于金融领域的交易撮合系统Disruptor简介Disruptor是英国外汇交易公司LMAX开发的一个高性能队列,研发的初衷是解决内存队列的延迟问题(在性能测试中发现竟然与I/O操作处于同样的数量级)。基于Disruptor开发的系统单线程能支撑每秒600万订单,2010年在QCon演讲后,获得了业界关注。2011年,企业应用软件专家Martin Fowler专门撰写长文介绍。同年它还获得了Oracle官方的Duke大奖。目前,包括A原创 2022-03-11 12:51:41 · 403 阅读 · 0 评论 -
并发编程之深入理解十三:CompletionService & CompletableFuture
CompletionServiceCallable + Future 可以实现多个task并行执行,但是如果遇到前面的task执行较慢时需要阻塞等待前面的task执行完后面task才能取得结果。而CompletionService的主要功能就是一边生成任务,一边获取任务的返回值。让两件事分开执行,任务之间不会互相阻塞,可以实现先执行完的先取结果,不再依赖任务顺序了。CompletionService原理内部通过阻塞队列+FutureTask,实现了任务先完成可优先获取到,即结果按照完成先后顺序排序原创 2022-03-11 16:01:15 · 1095 阅读 · 0 评论 -
并发编程之深入理解十二:Callable & Future & FutureTask
Callable & Future & FutureTask 介绍直接继承Thread或者实现Runnable接口都可以创建线程,但是这两种方法都有一个问题 就是:没有返回值,也就是不能获取执行完的结果。因此java1.5就提供了Callable接口来实现 这一场景,而Future和FutureTask就可以和Callable接口配合起来使用。Callable和Runnable的区别思考:为什么需要 Callable?@FunctionalInterfacepublic inte原创 2022-03-11 15:53:00 · 141 阅读 · 0 评论 -
并发编程之深入理解十一:ForkJoin
任务类型思考: 线程池的线程数设置多少合适?我们调整线程池中的线程数量的最主要的目的是为了充分并合理地使用 CPU 和内存等资 源,从而最大限度地提高程序的性能。在实际工作中,我们需要根据任务类型的不同选择对应 的策略CPU密集型任务CPU密集型任务也叫计算密集型任务,比如加密、解密、压缩、计算等一系列需要大量耗费 CPU 资源的任务。对于这样的任务最佳的线程数为 CPU 核心数的 1~2 倍,如果设置过多的 线程数,实际上并不会起到很好的效果。此时假设我们设置的线程数量是 CPU 核心数的 2 倍原创 2022-03-11 11:18:24 · 559 阅读 · 0 评论 -
并发编程之深入理解十:线程池
ThreadPoolExecutorThreadPoolExecutorprivate static final int COUNT_BITS = Integer.SIZE - 3;private static final int CAPACITY = (1 << COUNT_BITS) - 1;// runState is stored in the high-order bitsprivate static final int RUNNING = -1 <<.原创 2022-03-10 18:10:42 · 247 阅读 · 1 评论 -
并发编程之深入理解九:阻塞队列 BlockingQueue
阻塞队列 BlockingQueue阻塞队列介绍Queue接口public interface Queue<E> extends Collection<E> { //添加一个元素,添加成功返回true, 如果队列满了,就会抛出异常 boolean add(E e); //添加一个元素,添加成功返回true, 如果队列满了,返回false boolean offer(E e); //返回并删除队首元素,队列为空则抛出异常 E rem原创 2022-03-04 18:21:42 · 154 阅读 · 0 评论 -
并发编程之深入理解八:AQS之 ReentrantReadWriteLock
读写锁介绍现实中有这样一种场景:对共享资源有读和写的操作,且写操作没有读操作那么频繁(读多写少)。在没有写操作的时候,多个线程同时读一个资源没有任何问题,所以应该允许多个线程同时读取共享资源(读读可以并发);但是如果一个线程想去写这些共享资源,就不应该允许其他线程对该资源进行读和写操作了(读写,写读,写写互斥)。在读多于写的情况下,读写锁能够提供比排它锁更好的并发性和吞吐量。针对这种场景,JAVA的并发包提供了读写锁ReentrantReadWriteLock,它内部,维护了一对相关的锁,一个用于原创 2022-03-04 17:00:20 · 74 阅读 · 0 评论 -
并发编程之深入理解七:AQS之Semaphorer & CountDownLatch & CyclicBarrie
Semaphore介绍Semaphore,俗称信号量,它是操作系统中PV操作的原语在java的实现,它也是基于 AbstractQueuedSynchronizer实现的。Semaphore的功能非常强大,大小为1的信号量就类似于互斥锁,通过同时只能有一个线程获 取信号量实现。大小为n(n>0)的信号量可以实现限流的功能,它可以实现只能有n个线程同 时获取信号量。PV操作是操作系统一种实现进程互斥与同步的有效方法。PV操作与信号量(S)的处理相关,P表示通 过的意思,V表示释放的意思。用PV操原创 2022-03-04 15:26:53 · 109 阅读 · 0 评论 -
并发编程之深入理解六:AQS之独占锁ReentrantLock
AQS原理分析什么是AQSjava.util.concurrent包中的大多数同步器实现都是围绕着共同的基础行为,比如等待队列、条件队列、独占获取、共享获取等,而这些行为的抽象就是基于 AbstractQueuedSynchronizer(简称AQS)实现的,AQS是一个抽象同步框架,可以用来实 现一个依赖状态的同步器。JDK中提供的大多数的同步器如Lock, Latch, Barrier等,都是基于AQS框架来实现的一般是通过一个内部类Sync继承AQS 将同步器所有调用都映射到Sync对应原创 2022-03-04 12:15:55 · 93 阅读 · 0 评论 -
并发编程之深入理解五:synchronized
synchronized底层原理synchronized是JVM内置锁,基于Monitor机制实现,依赖底层操作系统的互斥原语Mutex(互斥量),它是一个重量级锁,性能较低。当然,JVM内置锁在1.5之后版本做了重大的优化,如锁粗化(Lock Coarsening)、锁消除(Lock Elimination)、轻量级锁(Lightweight Locking)、偏向锁(Biased Locking)、自适应自旋(Adaptive Spinning)等技术来减少锁操 作的开销,内置锁的并发性能已经基本与原创 2022-03-04 11:06:32 · 185 阅读 · 0 评论 -
并发编程之深入理解四:LockSupport park & unpark
LockSupport park & unpark使用wait/notify阻塞唤醒线程使用wait,notify来实现等待唤醒功能至少有两个缺点:wait和notify都是Object中的方法,在调用这两个方法前必须先获得锁对象,这限制了其使用场合:只能在同步代码块中。当对象的等待队列中有多个线程时,notify只能随机选择一个线程唤醒,无法唤醒指定的线程使用LockSupport的话,我们可以在任何场合使线程阻塞,同时也可以指 定要唤醒的线程,相当的方便使用park/unpark原创 2022-03-03 12:33:15 · 220 阅读 · 0 评论 -
并发编程之深入理解三:Atomic
并发工具之Atomic原子操作类详解Atomic原子操作类介绍在J.U.C下的atomic包提供了一系列的操作简单, 性能高效,并能保证线程安全的类去更新基本类型变量,数组元素,引用类型以及更新对象中的 字段类型。atomic包下的这些类都是采用的是乐观锁策略去原子更新数据,在java中则是使用 CAS操作具体实现。在java.util.concurrent.atomic包里提供了一组原子操作类:基本类型:AtomicInteger、AtomicLong、AtomicBoolean; 引用类型:At原创 2022-03-03 12:15:26 · 61 阅读 · 0 评论 -
并发编程之深入理解二:CAS
什么是 CASCAS(Compare And Swap,比较并交换),通常指的是这样一种原子操作:针对一个变量,首 先比较它的内存值与某个期望值是否相同,如果相同,就给它赋一个新值。CAS 的逻辑用伪代码描述如下:if(value==expectedValue){ value = newValue;}以上伪代码描述了一个由比较和赋值两阶段组成的复合操作,CAS 可以看作是它们合并后的整体 ——一个不可分割的原子操作,并且其原子性是直接在硬件层面得到保障的。 CAS可以看做是乐观锁(对比数据原创 2022-03-03 11:59:38 · 125 阅读 · 0 评论 -
并发编程之深入理解一: Java线程
进程、线程、切换查看查看进程线程的方法linuxps -fe 查看所有进程ps -fT -p 查看某个进程(PID)的所有线程 kill 杀死进程top 按大写 H 切换是否显示线程top -H -p 查看某个进程(PID)的所有线程通过命令查看CPU上下文切换情况linux系统可以通过命令统计CPU上下文切换数据#可以看到整个操作系统每1秒CPU上下文切换的统计vmstat 1其中cs列就是CPU上下文切换的统计。查看某一个线程\进程的上下文切换使用pidstat命令常用的原创 2022-03-03 11:38:36 · 90 阅读 · 0 评论 -
并发编程:并发(多线程)设计模式
并发(多线程)设计模式一、终止线程的设计模式 两阶段终止-interruptTwo-phase Termination(两阶段终止-interrupt)模式——优雅的终止线程使用场景思考:在一个线程 T1 中如何正确安全的终止线程 T2?错误思路1: 使用线程对象的 stop() 方法停止线程stop 方法会真正杀死线程,如果这时线程锁住了共享资源,那么当它被杀死后就再也没有机会释放锁, 其它线程将永远无法获取锁。错误思路2: 使用 System.exit(int) 方法停止线程目的原创 2022-02-25 16:46:21 · 400 阅读 · 0 评论 -
并发编程:提问(三)
并发编程面试题目1. 在 Java 中守护线程和用户线程的区别?Java 中的线程分为两种:守护线程(Daemon)和用户线程(User)。任何线程都可以设置为守护线程和用户线程,通过方法 Thread.setDaemon(boolon); true 则把该线程设置为守护线程,反之则为用户线程。Thread.setDaemon()必须在 Thread.start()之前调用,否则运行时会抛出异常。两者的区别:唯一的区别是判断虚拟机(JVM)何时离开,Daemon 是为其他线程提供服务,如果全部 的原创 2022-02-23 17:14:04 · 83 阅读 · 0 评论 -
并发编程:提问(二)
1)现在有 T1、T2、T3 三个线程,你怎样保证 T2 在 T1 执行完后执行,T3 在 T2 执行完后执 行?使用Thread.join()实现使用单线程线程池来实现 ExecutorService executor = Executors.newSingleThreadExecutor();使用volatile关键字修饰的信号量实现 volatile int ticket = 1; while (true) { if (ticket == name) {...... }}使用Lock和信号量原创 2022-02-22 16:25:47 · 78 阅读 · 0 评论 -
并发编程:提问(一)
一、JAVA如何开启线程? 怎么保证线程安全?线程和进程的区别:进程是操作系统进行资源分配的最小单元。线程是操作系统进行任务分配的最小单元,线程隶属于进程。如何开启线程?1、继承Thread类,重写run方法。 class MyThread extends Thread2、实现Runnable接口,实现run方法。 class MyRunnable implements Runnable3、实现Callable接口,实现call方法。通过FutureTask创建一个线程,获取到线程执行的返回值。原创 2022-02-21 16:50:30 · 71 阅读 · 0 评论