
多线程
文章平均质量分 52
多线程
weixin_42868638
这个作者很懒,什么都没留下…
展开
-
三.多线程JUC篇-3.28 CopyOnWriteArrayList
1.什么是CopyOnWrite容器CopyOnWrite容器即写时复制的容器。通俗的理解是当我们往一个容器添加元素的时候,不直接往当前容器添加,而是先将当前容器进行Copy,复制出一个新的容器,然后新的容器里添加元素,添加完元素之后,再将原容器的引用指向新的容器。这样做的好处是我们可以对CopyOnWrite容器进行并发的读,而不需要加锁,因为当前容器不会添加任何元素。所以CopyOnWrite容器也是一种读写分离的思想,读和写不同的容器。2.CopyOnWriteArrayList的实现原理读的原创 2021-01-06 15:04:55 · 97 阅读 · 0 评论 -
三.多线程JUC篇-3.27 LinkedBlockingQueue与ConcurrentLinkedQueue的区别
1.阻塞队列与非阻塞队列队列是一种常见的数据结构,先进先出,在日常工作中有着高频率的使用。在 Java 中应用也更为广泛,是生产消费模型首选的数据结构,简化了开发,解耦生产与消费的关系。Java中 Queue 可以分为阻塞队列和非阻塞队列。1.1 阻塞队列非阻塞队列也就是一般的队列,没有阻塞队列的两个阻塞功能。其主要方法如下:boolean add(E e):将元素e插入到队列末尾,插入成功,返回true;插入失败(即队列已满),抛出异常;boolean offer(E e):将元素e插入原创 2021-01-06 14:41:20 · 198 阅读 · 0 评论 -
三.多线程JUC篇-3.26 ConcurrentSkipListMap
1.前言TreeMap对应的线程安全是ConcurrentSkipListMapHashMap对应的线程安全是concurrentHashMap2.concurrentHashMap与ConcurrentSkipListMap性能测试在4线程1.6万数据的条件下,ConcurrentHashMap 存取速度是ConcurrentSkipListMap 的4倍左右。但ConcurrentSkipListMap有几个ConcurrentHashMap 不能比拟的优点:ConcurrentSki原创 2021-01-06 14:11:58 · 128 阅读 · 1 评论 -
三.多线程JUC篇-3.27 ConcurrentHashMap
1. 1.7中实现原理一个ConcurrentHashMap里包含一个Segment数组,每个Segment里包含一个HashEntry数组,我们称之为table,每个HashEntry是一个链表结构的元素。Segment实际继承自可重入锁(ReentrantLock),在ConcurrentHashMap里扮演锁的角色;HashEntry则用于存储键值对数据。如何在保证高并发下线程安全的同时实现了性能提升?ConcurrentHashMap允许多个修改操作并发进行,其关键在于使用了锁分离技原创 2021-01-06 13:27:01 · 108 阅读 · 0 评论 -
三.多线程JUC篇-3.26 LinkedTransferQueue
担保递出去的元素必须消费tryTransfer:如果没有consumer是返回false原创 2021-01-05 14:54:11 · 101 阅读 · 0 评论 -
三.多线程JUC篇-3.25 LinkedBlockingDeque
LinkedBlockingDeque是双向链表实现的双向并发阻塞队列。该阻塞队列同时支持FIFO和FILO两种操作方式,即可以从队列的头和尾同时操作(插入/删除);并且,该阻塞队列是支持线程安全。空间容量最大一般为Integer.MAX_VALUE,如果构造器中指定了最大值则队列长度将会被限制在该值以下。...原创 2021-01-05 14:13:13 · 81 阅读 · 0 评论 -
三.多线程JUC篇-3.24 DelayQueue
1.简介DelayQueue是一个无界的BlockingQueue,用于放置实现了Delayed接口的对象,其中的对象只能在其到期时才能从队列中取走。2.使用场景:DQueue非常有用的。我们利用DQueue的延时特性,可以讲DQueue应用于以下场景:缓存的设计:可以利用Dqueue保存缓存元素的有效期。使用一个线程循环的从队列中获取数据。一旦获取到数据,就说明缓存有效期到了。定时任务调度:可以使用Dqueue保存需要执行的任务和任务执行的时间,一旦从DQueue中获取到了任务,就开始执原创 2021-01-05 14:03:46 · 112 阅读 · 0 评论 -
三.多线程JUC篇-3.23 SynchronousQueue
1.介绍SynchronousQueue是无界的,是一种无缓冲的等待队列但是由于该Queue本身的特性,在某次添加元素后必须等待其他线程取走后才能继续添加可以认为SynchronousQueue是一个缓存值为1的阻塞队列,但是 isEmpty()方法永远返回是true,remainingCapacity() 方法永远返回是0,remove()和removeAll() 方法永远返回是false,iterator()方法永远返回空,peek()方法永远返回null。2.模式公平模式:Synch原创 2021-01-05 10:04:33 · 101 阅读 · 0 评论 -
三.多线程JUC篇-3.22 LinkedBlockingQueue
1.概述LinkedBlockingQueue内部由单链表实现,只能从head取元素,从tail添加元素。添加元素和获取元素都有独立的锁,也就是说LinkedBlockingQueue是读写分离的,读写操作可以并行执行。LinkedBlockingQueue采用可重入锁(ReentrantLock)来保证在并发情况下的线程安全。LinkedBlockingQueue可以指定边界,也可以是无边界2.构造器LinkedBlockingQueue一共有三个构造器,分别是无参构造器、可以指定容量的构造原创 2021-01-05 08:44:15 · 273 阅读 · 0 评论 -
三.多线程JUC篇-3.21 PriorityBlockingQueue
指定一个初始容器大小,但支持自动扩容,直到系统资源耗尽一个支持优先级的无界阻塞队列容器中的元素需要支持comparable。或者初始化PriorityBlockingQueue时,指定构造参数Comparator来对元素进行排序...原创 2021-01-04 13:56:54 · 100 阅读 · 0 评论 -
三.多线程JUC篇-3.20 ArrayBlockingQueue
1. 阻塞处理方式BlockingQueue 方法以四种形式出现,对于不能立即满足但可能在将来某一时刻可以满足的操作,这四种形式的处理方式不同:抛出一个异常返回一个特殊值(null 或 false,具体取决于操作)在操作可以成功前,无限期地阻塞当前线程在放弃前只在给定的最大时间限制内阻塞。下表中总结了这些方法:抛出异常特殊值阻塞超时插入add(e)offer(e)put(e)offer(e, time, unit)移除remove()poll()原创 2021-01-04 09:26:54 · 112 阅读 · 0 评论 -
三.多线程JUC篇-3.19 CompletionService
1.future的缺陷package com.dwz.executors;import java.util.ArrayList;import java.util.Arrays;import java.util.List;import java.util.concurrent.Callable;import java.util.concurrent.ExecutionException;import java.util.concurrent.ExecutorService;import ja原创 2020-12-30 13:35:04 · 174 阅读 · 0 评论 -
三.多线程JUC篇-3.18 Future 详细讲解
1.get和interruptprivate static void testGet() throws InterruptedException, ExecutionException { ExecutorService executorService = Executors.newCachedThreadPool(); Future<Integer> future = executorService.submit(() -> {原创 2020-12-29 13:38:57 · 311 阅读 · 1 评论 -
三.多线程JUC篇-3.17 ExecutorService API详细讲解
1.shutdownpublic class ExecutorServiceExample1 { public static void main(String[] args) throws InterruptedException { isShutDown(); } private static void isShutDown() { ExecutorService executorService = Executors.newSingleThre原创 2020-12-28 16:57:12 · 304 阅读 · 0 评论 -
三.多线程JUC篇-3.16 Executors
2.useCachedThreadPool创建一个可按需自动扩容的线程池,但是会优先重用线程池中空闲可用的线程。这个类型的线程池将会大大提升执行许多短暂的异步任务的程序。public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) { return new ThreadPoolExecutor(0, 2147483647, 60L, TimeUnit.SECONDS, new原创 2020-11-17 11:36:47 · 121 阅读 · 0 评论 -
三.多线程JUC篇-3.15 ThreadPoolExecutor
corePoolSize:常驻核心线程数,也就是说这是线程池中始终存活的线程,即使是空闲状态,也不会被销毁,除非关闭线程池。但有个特殊,设置了allowCoreThreadTimeout,线程池中corePoolSize线程空闲时间达到keepAliveTime也将关闭maximumPoolSize:最大线程数,线程池中最多能存活的线程数keepAliveTime:空闲线程存活时间,配合下一个参数unit,当线程池中的线程数量超过corePoolSize,会清空多余的线程数量,以便使线程池数..原创 2020-11-16 14:40:01 · 95 阅读 · 0 评论 -
三.多线程JUC篇-3.14 Executor&ExecutorService讲解
1.概述在Java 5之后,并发编程引入了一堆新的启动、调度和管理线程的API。Executor框架便是Java 5中引入的,其内部使用了线程池机制,它在java.util.cocurrent 包下,通过该框架来控制线程的启动、执行和关闭,可以简化并发编程的操作Eexecutor作为灵活且强大的异步执行框架,其支持多种不同类型的任务执行策略,提供了一种标准的方法将任务的提交过程和执行过程解耦开发,基于生产者-消费者模式,其提交任务的线程相当于生产者,执行任务的线程相当于消费者,并用Runnabl原创 2020-11-16 11:45:01 · 144 阅读 · 0 评论 -
三.多线程JUC篇-3.13 Phaser工具
前言Phaser是JDK1.7提供的一种同步工具,是可重用的同步屏障,其功能类似于CyclicBarrier和CountDownLatch,但支持更灵活的用法。本篇主要讲解Phaser、Exchanger两种工具的用法。其更加灵活的地方就在于:可以阶段性的控制各个线程的行为。举个例子总共六位同学要参加同学聚会,聚会流程有三项:吃饭、K歌、看电影。六位同学都要吃饭,但是吃完饭后只有四位同学想K歌,K完歌后只有两位同学想看电影。实现这样的场景,用CyclicBarrier和CountDownLatch原创 2020-11-16 11:00:33 · 136 阅读 · 0 评论 -
三.多线程JUC篇-3.12 RecursiveTask和RecursiveAction
1.Fork/Join框架Fork/Join框架是Java7提供了的一个用于并行执行任务的框架, 是一个把大任务分割成若干个小任务,最终汇总每个小任务结果后得到大任务结果的框架。我们再通过Fork和Join这两个单词来理解下Fork/Join框架,Fork就是把一个大任务切分为若干子任务并行的执行,Join就是合并这些子任务的执行结果,最后得到这个大任务的结果。比如计算1+2+…+10000,可以分割成10个子任务,每个子任务分别对1000个数进行求和,最终汇总这10个子任务的结果Fork原创 2020-11-13 14:52:43 · 400 阅读 · 0 评论 -
三.多线程JUC篇-3.11 StampedLock
1.为什么会有StampedLock饥饿问题:ReentrantReadWriteLock实现了读写分离,想要获取读锁就必须确保当前没有其他任何读写锁了,但是一旦读操作比较多的时候,想要获取写锁就变得比较困难了,因为当前有可能会一直存在读锁。而无法获得写锁。这时候怎么办呢?于是在jdk1.8的时候引入了一个新的锁StampedLock。2.StampedLock介绍StampedLock控制锁有三种模式(写,悲观读,乐观读),一个StampedLock状态是由版本和模式两个部分组成,锁获取方法返原创 2020-11-12 11:24:23 · 100 阅读 · 0 评论 -
三.多线程JUC篇-3.10 ReentrantLock
一.概念ReentrantLock重入锁,是实现Lock接口的一个类,也是在实际编程中使用频率很高的一个锁支持重入性,表示能够对共享资源能够重复加锁,即当前线程获取该锁再次获取不会被阻塞(1) 在线程获取锁的时候,如果已经获取锁的线程是当前线程的话则直接再次获取成功(2) 由于锁会被获取n次,那么只有锁在被释放同样的n次之后,该锁才算是完全释放成功ReentrantLock还支持公平锁和非公平锁两种方式二.与synchronized比较ReentarntLock可以添加多个检控条件(co原创 2020-11-11 11:52:23 · 117 阅读 · 0 评论 -
三.多线程JUC篇-3.9 控制并发线程数的Semaphore
1.简介Semaphore(信号量)是用来控制同时访问特定资源的线程数量,它通过协调各个线程,以保证合理的使用公共资源。Semaphore 是 synchronized 的加强版,作用是控制线程的并发数量2.应用场景很多年以来,我都觉得从字面上很难理解Semaphore所表达的含义,只能把它比作是控制流量的红绿灯,比如XX马路要限制流量,只允许同时有一百辆车在这条路上行使,其他的都必须在路口等待,所以前一百辆车会看到绿灯,可以开进这条马路,后面的车会看到红灯,不能驶入XX马路,但是如果前一百原创 2020-11-10 16:05:03 · 2236 阅读 · 0 评论 -
三.多线程JUC篇-3.8 Exchanger
1.简介Exchanger(交换者)是一个用于线程间协作的工具类,Exchanger用于进行线程间的数据交换。它提供一个同步点,在这个同步点两个线程可以交换彼此的数据。这两个线程通过exchange方法交换数据, 如果第一个线程先执行exchange方法,它会一直等待第二个线程也执行exchange,当两个线程都到达同步点时,这两个线程就可以交换数据,将本线程生产出来的数据传递给对方。Exchanger类提供了两个方法:(1) String exchange(V x):用于交换,启动交换并等待另一原创 2020-11-10 15:29:45 · 179 阅读 · 0 评论 -
三.多线程JUC篇-3.7 CyclicBarrier
1.概念多个线程相互等待,直到所有线程到达同一个同步点,再继续一起执行2.实现原理在CyclicBarrier的内部定义了一个Lock对象,每当一个线程调用await方法时,将拦截的线程数减1,然后判断剩余拦截数是否为初始值parties,如果不是,进入Lock对象的条件队列等待。如果是,执行barrierAction对象的Runnable方法,然后将锁的条件队列中的所有线程放入锁等待队列中,这些线程会依次的获取锁、释放锁。3.与countDown()比较CountDownLatch是线程组之间原创 2020-11-06 14:00:21 · 99 阅读 · 0 评论 -
三.多线程JUC篇-3.6 CountDownLatch
1.概述countDownLatch这个类使一个线程等待其他线程各自执行完毕后再执行。是通过一个计数器来实现的,计数器的初始值是线程的数量或者任务的数量。每当一个线程执行完毕后,计数器的值就-1,当计数器的值为0时,表示所有线程都执行完毕,然后在闭锁上等待的线程就可以恢复工作了。CountDownLatch的方便之处在于,你可以在一个线程中使用,也可以在多个线程上使用,一切只依据状态值,这样便不会受限于任何的场景。2.分析在java5提供的并发包下,有一个AbstractQueuedSync转载 2020-11-06 10:22:51 · 116 阅读 · 0 评论 -
三.多线程JUC篇-3.5 LongAdder
1.LongAdder原理LongAdder是根据ConcurrentHashMap这类为并发设计的类的基本原理——锁分段,来实现的,它里面维护一组按需分配的计数单元,并发计数时,不同的线程可以在不同的计数单元上进行计数,这样减少了线程竞争,提高了并发效率。本质上是用空间换时间的思想,不过在实际高并发情况中消耗的空间可以忽略不计。使用LongAdder时,内部维护了多个Cell变量,每个Cell里面有一个初始值为0的long型变量,这样同时争取一个变量的线程就变少了,而是分散成对多个变量的竞争,减少了原创 2020-11-03 15:05:29 · 175 阅读 · 0 评论 -
三.多线程JUC篇-3.4 AtomicIntegerFieldUpdater
一、AtomicIntegerFieldUpdater对类中volatile修饰的字段进行原子更新二、 使用稍微有一些限制和约束,约束如下:字段必须是volatile类型的,在线程之间共享变量时保证立即可见.eg:volatile int value = 3字段的描述类型(修饰符public/protected/default/private)是与调用者与操作对象字段的关系一致。也就是说调用者能够直接操作对象字段,那么就可以反射进行原子操作。但是对于父类的字段,子类是不能直接操作的,尽管子类可原创 2020-11-03 13:55:58 · 189 阅读 · 0 评论 -
三.多线程JUC篇-3.3 AtomicReference和AtomicStampReference
虽然无锁比较交换让代码看起来比直接加锁复杂一点点,但是无锁比较交换能提供更高的效率,没错,且不存在死锁问题,但是无锁操作不是所有场景下都是安全的。先用最简单直白的概括回顾下CAS,有三个参数V,E,N,只有当“预期值”E和对象V的值相等时,才把V的值更新为“更新值”V。可以看到,是否修改V的值,取决于V的值和E是否相等,如果不相等,那么程序就会重新读取V的值,直到V的值与E相等后,才做修改操作(当然也可以放弃等待)。这样做看似没什么问题,但是在某些特定场景下,和实际应用中,是存在一些问题的,..原创 2020-11-03 10:47:32 · 314 阅读 · 0 评论 -
三.多线程JUC篇-3.2 AtomicInteger
1.前言java.util.concurrent.atomic 的包里有AtomicBoolean, AtomicInteger,AtomicLong,AtomicLongArray,AtomicReference等原子类的类,主要用于在高并发环境下的高效程序处理,来帮助我们简化同步处理.在Java语言中,++i和i++操作并不是线程安全的,在使用的时候,不可避免的会用到synchronized关键字(解决了有序性、可见性,但没有解决原子性)。而AtomicInteger则通过一种线程安全的加转载 2020-11-02 10:33:25 · 121 阅读 · 0 评论 -
三.多线程JUC篇-3.1 Unsafe
Java和C++语言的一个重要区别就是Java中我们无法直接操作一块内存区域,不能像C++中那样可以自己申请内存和释放内存。Java中的Unsafe类为我们提供了类似C++手动管理内存的能力。Unsafe类,全限定名是sun.misc.Unsafe,从名字中我们可以看出来这个类对普通程序员来说是“危险”的,一般应用开发者不会用到这个类。Unsafe类是"final"的,不允许继承。且构造函数是private的:public final class Unsafe { private sta原创 2020-10-30 16:13:56 · 190 阅读 · 2 评论 -
二.多线程设计模式篇-2.2 观察者设计模式在多线程中的运用
1.观察者设计模式简单来说,观察者模式=发布者+订阅者。典型的例子:猎头和寻找工作的人。找工作的人向猎头订阅,告知自己希望得到一份工作,当有新的工作机会的时候,猎头就会把这个信息通知给曾经向他订阅过的人。2.多线程使用观察者设计模式这里有一个场景,有个批查询请求,为了应对这种情况,需要开启一定的子线程,将批查询分拆几个小的查询,然后同步处理。主线程能够实时监控到子线程运行状态,保证子线程运行完能够通知的主线程。1.主题类public class ObservableRunnable impl原创 2020-09-25 16:49:21 · 329 阅读 · 0 评论 -
二.多线程设计模式篇-2.13 Worker-Thread设计模式
Worker是“工人”的意思,worker thread pattern中,工人线程(worker thread)会一次抓一件工作来处理,当没有工作可做时,工人线程会停下来等待心得工作过来。Worker Thread模式在Request的管理上像是 Producer Consumer 模式,在Request的行为上像是 Command 模式。Producer Consumer模式专注于Product的生产与消费,至于Product被消费时是作何处理,则不在它的讨论范围之中。如果您的Product是一转载 2020-10-13 16:31:16 · 223 阅读 · 0 评论 -
二.多线程设计模式篇-2.12 Two Phase Termination设计模式
1.定义 我们将线程的正常处理状态称为“作业中”,当希望结束这个线程时,则送出“终止请求”。接着,这个线程并不会立刻结束,而是进入“终止处理中”状态,此时线程还是运行着的,可能处理一些释放资源等操作。直到终止处理完毕,才会真正结束。Two-phase Termination主要考虑以下问题:安全地约束(安全性)一定会进行终止处理(生命性)收到“终止请求”后,要尽快进行终止处理(响应性)2.例子1.Counterpublic class Counter原创 2020-10-13 15:03:47 · 147 阅读 · 0 评论 -
二.多线程设计模式篇-2.11 Thread-Per-Message设计模式
1.概念翻译过来就是每个消息一个线程。message可以理解为命令,请求。为每一个请求新分配一个线程,由这个线程来执行处理。Thread-Per-Message模式中,请求的委托端和请求的执行端是不同的线程,请求的委托端会告诉请求的执行端线程:这项工作就交给你了2.示例程序(1)Host类:针对请求创建线程的类(2)Helper类:执行端,实际进行请求的处理public class Helper { public void handle(int count, char c){原创 2020-10-13 14:39:16 · 209 阅读 · 0 评论 -
二.多线程设计模式篇-2.10 Count Down设计模式
1.概述Count-Down设计模式其实也叫做Latch(阀门)设计模式。当若干个线程并发执行完某个特定的任务,然后等到所有的子任务都执行结束之后再统一汇总。2.JDK自带CountDownLatchpublic static void main(String[] args) throws InterruptedException { //设置countdown为5 CountDownLatch countDownLatch = new CountDownLatch(5); System.转载 2020-10-13 14:26:17 · 174 阅读 · 0 评论 -
二.多线程设计模式篇-2.9 多线程Producer and Consumer设计模式
1.问题的引入 有一个工厂,他负责生产商品,他有很多工人,每天能生产出很多种类的商品,但是,他并不知道客户的消费情况,这也就造成了如果他产能过剩时,他将会有生产浪费的可能。在Java程序中,若出现这种情况,则会产生内存的使用量过高,甚至有可能产生内存溢出发的可能。2. 解决的方案利用中间生产的限额标定,即可解决产能过剩的情况。3. 代码的实现(1)货物/** * 货物 */public class Production { private final String data;转载 2020-10-13 10:02:13 · 220 阅读 · 0 评论 -
二.多线程设计模式篇-2.8 Balking设计模式
1.概念多个线程监控某个共享变量,A线程监控到共享变量发生变化后即将触发某个动作,但是此时发现有另外一个线程B已经针对该变量的变化开始了行动,因此A便放弃了准备开始的动作,我们把这样的线程间交互成为Balking(犹豫)设计模式。2.应用场景其实这样的场景在生活中很常见,比如你去饭店吃饭,吃到途中想要再点一个小菜,于是你举起手示意服务员,其中一个服务员看到了你举手正准备走过来的时候,发现距离你比较近的服务员已经准备要受理你的请求于是中途放弃了。再比如,我们在用word编写文档的时候,每次的文字编辑转载 2020-10-10 16:16:48 · 196 阅读 · 0 评论 -
二.多线程设计模式篇-2.7 ThreadLocal
1.ThreadLocal是什么从名字我们就可以看到ThreadLocal叫做线程变量,意思是ThreadLocal中填充的变量属于当前线程,该变量对其他线程而言是隔离的。ThreadLocal为变量在每个线程中都创建了一个副本,那么每个线程可以访问自己内部的副本变量。从字面意思来看非常容易理解,但是从实际使用的角度来看,就没那么容易了,作为一个面试常问的点,使用场景那也是相当的丰富:在进行对象跨层传递的时候,使用ThreadLocal可以避免多次传递,打破层次间的约束。线程间数据隔离进行事务操转载 2020-10-09 14:12:27 · 78 阅读 · 0 评论 -
二.多线程设计模式篇-2.6 Guarded Suspension设计模式
1.概念如果执行现在的处理会造成问题,就让执行处理的线程等待。这种模式通过让线程等待来保证实例的安全性2.核心思想当且仅当服务进程准备好时,才提供服务。设想一种场景,服务器可能会在很短时间内承受大量的客户端请求,客户端请求的数量可能超过服务器本身的即时处理能力,而服务端程序又不能丢弃任何一个客户请求。此时,最佳的处理方案莫过于让客户端请求进行排队,由服务端程序一个接一个处理。这样,既保证了所有的客户端请求均不丢失,同时也避免了服务器由于同时处理太多请求而崩溃。3.例子Requestpubli原创 2020-09-30 09:53:18 · 108 阅读 · 0 评论 -
二.多线程设计模式篇-2.5 Future设计模式
一、Future设计模式有什么好处假如有一个执行起来需要花费一些时间的方法,为了省去不必要的等待执行结果出来,继续做别的事情,则可以事先获取一个“提货单”即Future参与者二、Future几个概念Future:未来,可以理解为票据,先获取这样一个票据,然后在未来的时刻里,通过票据,获取任务处理结果TASK:任务,比较重的任务FutureServer:桥接Future和TASK,会启动一个线程,单独执行TASK,待任务执行完,会改变Future状态,表明可以获取结果啦三、例子1.Futur原创 2020-09-27 16:22:41 · 89 阅读 · 0 评论