
并发编程
文章平均质量分 82
Java并发编程
吴声子夜歌
个人学习记录
展开
-
Java并发——ScheduledExecutorService
ScheduledExecutorService类 Scheduledexecutor Service的主要作用就是可以将定时任务与线程池功能结合使用。ScheduledThreadPoolExecutor使用Callable延迟运行public class MyCallableAA implements Callable<String> { @Override public String call() throws Exception { try {原创 2020-06-24 20:33:43 · 2925 阅读 · 0 评论 -
Java并发——CompletionService
CompletionService接口CompletionService的功能是以异步的方式生产新的任务,一边处理已完成任务的结果,这样可以将执行任务与处理任务分离开来进行处理。使用submit执行任务,使用take取得已完成的任务,并按照完成这些任务的时间顺序处理它们的结果。接口 Completion Service的结构比较简洁,仅有一个实现类 Executor Completion Service,该类的构造方法如图所示。从构造方法的声明中可以发现,类 Executor Completion原创 2020-06-24 14:14:56 · 841 阅读 · 0 评论 -
Java并发——Future和Callable
Future和CallableCallable和Runnable主要区别为:Callable接口的call)方法可以有返回值,而Runnable接口的run()方法没有返回值。Callable 接口的call0)方法可以声明抛出异常,而Runnable接口的run()方法不可以声明抛出异常。执行完Callable接口中的任务后,返回值是通过Future 接口进行获得的。get()和ExecutorService中的submit()和isDone()的使用方法submit()不仅可以传人Cal原创 2020-06-24 11:36:23 · 293 阅读 · 0 评论 -
Java并发——ThreadPoolExecutor详解(二)
工厂ThreadFactory+execute()+UncaughtExceptionHandler处理异常public class Run4 { public static void main(String[] args) { ThreadPoolExecutor pool = new ThreadPoolExecutor(2, 99999, 9999L, TimeUnit.SECONDS, new LinkedBlockingDeque<R原创 2020-06-23 17:32:02 · 972 阅读 · 0 评论 -
Java并发——ThreadPoolExecutor详解(一)
ThreadPoolExecutor类ThreadPoolExecutor可以非常方便地创建线程池对象,而不需要程序员设计大量的new实例化Thread相关的代码。构造:ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue)corePoolSize:池中所保存的线程数,包括空闲线程,也就原创 2020-06-23 13:44:31 · 1829 阅读 · 0 评论 -
Java并发——Phaser详解
PhaserPhaser中文翻译为相位器。它与CountDownLatch非常相似,允许我们协调线程的执行。与CountDownLatch相比,它具有一些额外的功能。Phaser是在线程动态数需要继续执行之前等待的屏障。在CountDownLatch中,该数字无法动态配置,需要在创建实例时提供。arriveAndAwaitAdvanve()方法:方arriveAndAwaitAdvanceo的作用与 CountDownLatch类中的awai()方法大体一样,通过从方法的名称解释来看, arriv原创 2020-06-22 23:28:14 · 1200 阅读 · 0 评论 -
Java并发——Exchanger
ExchangerExchanger的功能可以使2个线程之间传输数据,它比生产者/消费者模式使用的 wait/notify要更加方便。exchange()阻塞的特性:public class ThreadA extends Thread{ private Exchanger<String> exchanger; public ThreadA(Exchanger<String> exchanger) { this.exchanger = exch原创 2020-06-22 20:30:21 · 226 阅读 · 0 评论 -
Java并发——Semaphore
SemaphoreSemaphore即信号、信号系统。此类的主要作用就是限制线程并发的数量,如果不限制线程并发的数量,则CPU的资源很快就被耗尽,每个线程执行的任务是相当缓慢,因为CPU要把时间片分配给不同的线程对象,而且上下文切换也要耗时,最终造成系统运行效率大幅降低,所以限制并发线程的数量还是非常有必要的。Semaphore的同步性public class Service { private Semaphore semaphore = new Semaphore(1); publ原创 2020-06-22 01:05:43 · 404 阅读 · 0 评论 -
并发编程--偏向锁、轻量级锁
锁的升级与对比Java SE 1.6为了减少获得锁和释放锁带来的性能消耗,引入了“偏向锁”和“轻量级锁”,在 Java SE 1.6中,锁一共有4种状态,级别从低到高依次是:无锁状态、偏向锁状态、轻量级锁状 态和重量级锁状态,这几个状态会随着竞争情况逐渐升级。锁可以升级但不能降级,意味着偏 向锁升级成轻量级锁后不能降级成偏向锁。这种锁升级却不能降级的策略,目的是为了提高 获得锁和释放锁的效率。...原创 2020-02-25 11:59:11 · 243 阅读 · 0 评论 -
Java并发--对象头
Java对象头如果对象为非数组类型,用2字宽存储对象头。如果对象为数组类型,用3字宽存储对象头。在32位虚拟机中,1字宽 等于4字节,即32bit,如下表所示:对象头的组成Mark Word:Java对象头里的Mark Word里默认存储对象的HashCode、分代年龄和锁标记位。32位JVM 的Mark Word的默认存储结构如下:在运行期间,Mark Word里存储...原创 2020-02-25 11:46:51 · 376 阅读 · 0 评论 -
Java并发--FutureTask详解
FutureTaskFuture接口和实现Future接口的FutureTask类,代表异步计算的结果。FutureTask简介FutureTask除了实现Future接口外,还实现了Runnable接口。因此,FutureTask可以交给Executor执行,也可以由调用线程直接执行(FutureTask.run())。根据FutureTask.run()方法被执行的时机,FutureTa...原创 2020-01-22 16:50:30 · 2346 阅读 · 0 评论 -
Java并发--ScheduledThreadPoolExecutor
ScheduledThreadPoolExecutorScheduledThreadPoolExecutor继承自ThreadPoolExecutor。它主要用来在给定的延迟之后运行任务,或者定期执行任务。ScheduledThreadPoolExecutor的功能与Timer类似,但ScheduledThreadPoolExecutor功能更强大、更灵活。Timer对应的是单个后台线程,而S...原创 2020-01-22 16:35:41 · 688 阅读 · 0 评论 -
Java并发--ThreadPoolExecutor详解
ThreadPoolExecutor详解Executor框架最核心的类是ThreadPoolExecutor,它是线程池的实现类,主要由下列4个组件构成。corePool:核心线程池的大小。maximumPool:最大线程池的大小。BlockingQueue:用来暂时保存任务的工作队列。RejectedExecutionHandler:当ThreadPoolExecutor已经关闭或T...原创 2020-01-22 16:19:30 · 791 阅读 · 0 评论 -
Java并发--Executor框架
Executor框架在Java中,使用线程来异步执行任务。Java线程的创建与销毁需要一定的开销,如果我们为每一个任务创建一个新线程来执行,这些线程的创建与销毁将消耗大量的计算资源。同时,为每一个任务创建一个新线程来执行,这种策略可能会使处于高负荷状态的应用最终崩溃。Java的线程既是工作单元,也是执行机制。从JDK 5开始,把工作单元与执行机制分离开来。工作单元包括Runnable和Call...原创 2020-01-22 16:04:38 · 316 阅读 · 0 评论 -
Java并发--线程池的使用
线程池的创建我们可以通过ThreadPoolExecutor来创建一个线程池。创建一个线程池时需要输入几个参数,如下:corePoolSize(线程池的基本大小):当提交一个任务到线程池时,线程池会创建一个线程来执行任务,即使其他空闲的基本线程能够执行新任务也会创建线程,等到需要执行的任务数大于线程池基本大小时就不再创建。如果调用了线程池的prestartAllCoreThrea...原创 2020-01-22 15:35:29 · 293 阅读 · 0 评论 -
Java并发--线程池实现原理
Java中的线程池Java中的线程池是运用场景最多的并发框架,几乎所有需要异步或并发执行任务的程序都可以使用线程池。在开发过程中,合理地使用线程池能够带来3个好处。第一:降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。第二:提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。第三:提高线程的可管理性。线程是稀缺资源,如果无限制地创建,不仅会消耗系统资源...原创 2020-01-22 15:10:01 · 343 阅读 · 0 评论 -
Java并发--线程间交换数据的Exchanger
线程间交换数据的ExchangerExchanger(交换者)是一个用于线程间协作的工具类。 Exchanger用于进行线程间的数据交换。它提供一个同步点,在这个同步点,两个线程可以交换彼此的数据。这两个线程通过exchange方法交换数据,如果第一个线程先执行exchange()方法,它会一直等待第二个线程也执行exchange方法,当两个线程都到达同步点时,这两个线程就可以交换数据,将本线程...原创 2020-01-21 18:09:37 · 364 阅读 · 0 评论 -
Java并发--控制并发线程数的Semaphore
控制并发线程数的SemaphoreSemaphore(信号量)是用来控制同时访问特定资源的线程数量,它通过协调各个线程,以保证合理的使用公共资源。Semaphore比作是控制流量的红绿灯。比如××马路要限制流量,只允许同时有一百辆车在这条路上行使,其他的都必须在路口等待,所以前一百辆车会看到绿灯,可以开进这条马路,后面的车会看到红灯,不能驶入××马路,但是如果前一百辆中有5辆车已经离开了××马...原创 2020-01-21 17:58:06 · 559 阅读 · 0 评论 -
Java并发--同步屏障CyclicBarrier
同步屏障CyclicBarrierCyclicBarrier的字面意思是可循环使用(Cyclic)的屏障(Barrier)。它要做的事情是,让一组线程到达一个屏障(也可以叫同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续运行。CyclicBarrier简介CyclicBarrier默认的构造方法是CyclicBarrier(int parties),其...原创 2020-01-21 17:42:35 · 317 阅读 · 0 评论 -
Java并发--Fork/Join框架
什么是Fork/Join框架Fork/Join框架是Java 7提供的一个用于并行执行任务的框架,是一个把大任务分割成若干个小任务,最终汇总每个小任务结果后得到大任务结果的框架。我们再通过Fork和Join这两个单词来理解一下Fork/Join框架。Fork就是把一个大任务切分为若干子任务并行的执行,Join就是合并这些子任务的执行结果,最后得到这个大任务的结果。比如计算1+2+…+10000...原创 2020-01-21 16:58:00 · 349 阅读 · 0 评论 -
Java并发--阻塞队列的实现原理
阻塞队列的实现原理使用通知模式实现。 所谓通知模式,就是当生产者往满的队列里添加元素时会阻塞住生产者,当消费者消费了一个队列中的元素后,会通知生产者当前队列可用。通过查看JDK源码发现ArrayBlockingQueue使用了Condition来实现,代码如下。当往队列里插入一个元素时,如果队列不可用,那么阻塞生产者主要通过LockSupport.park(this)来实现。继续进入源码...原创 2020-01-21 16:20:13 · 1043 阅读 · 0 评论 -
Java并发--Java中的阻塞队列
什么是阻塞队列阻塞队列(BlockingQueue)是一个支持两个附加操作的队列。这两个附加的操作支持阻塞的插入和移除方法。支持阻塞的插入方法:意思是当队列满时,队列会阻塞插入元素的线程,直到队列不满。支持阻塞的移除方法:意思是在队列为空时,获取元素的线程会等待队列变为非空。阻塞队列常用于生产者和消费者的场景,生产者是向队列里添加元素的线程,消费者是从队列里取元素的线程。阻塞队...原创 2020-01-21 15:52:33 · 383 阅读 · 0 评论 -
Java并发--ConcurrentLinkedListQueue
ConcurrentLinkedListQueueConcurrentLinkedQueue是一个基于链接节点的无界线程安全队列,它采用先进先出的规则对节点进行排序,当我们添加一个元素的时候,它会添加到队列的尾部;当我们获取一个元素时,它会返回队列头部的元素。它采用了“wait-free”算法(即CAS算法)来实现,该算法在Michael&Scott算法上进行了一些修改。Concurr...原创 2020-01-21 15:38:21 · 2009 阅读 · 2 评论 -
Java并发--ConcurrentHashMap
为什么使用ConcurrentHashMap在并发编程中使用HashMap可能导致程序死循环。而使用线程安全的HashTable效率又非常低下,基于以上两个原因,便有了ConcurrentHashMap的登场机会。线程不安全的HashMap:在多线程环境下,使用HashMap进行put操作会引起死循环,导致CPU利用率接近100%,所以在并发情况下不能使用HashMap。例如,执行以下代码会...原创 2020-01-21 15:27:34 · 747 阅读 · 0 评论 -
Java并发--Condition的实现分析
Condition的实现分析ConditionObject是同步器AbstractQueuedSynchronizer的内部类,因为Condition的操作需要获取相关联的锁,所以作为同步器的内部类也较为合理。每个Condition对象都包含着一个队列(以下称为等待队列),该队列是Condition对象实现等待/通知功能的关键。等待队列等待队列是一个FIFO的队列,在队列中的每个节点都包含了...转载 2020-01-20 19:51:22 · 257 阅读 · 0 评论 -
Java并发--Condition接口
Condition接口任意一个Java对象,都拥有一组监视器方法(定义在java.lang.Object上),主要包括wait()、wait(long timeout)、notify()以及notifyAll()方法,这些方法与synchronized同步关键字配合,可以实现等待/通知模式。Condition接口也提供了类似Object的监视器方法,与Lock配合可以实现等待/通知模式,但是这两...原创 2020-01-20 19:36:34 · 310 阅读 · 0 评论 -
Java并发--LockSupport工具
LockSupport工具LockSupport定义了一组的公共静态方法,这些方法提供了最基本的线程阻塞和唤醒功能,而LockSupport也成为构建同步组件的基础工具。LockSupport定义了一组以park开头的方法用来阻塞当前线程,以及unpark(Thread thread)方法来唤醒一个被阻塞的线程。Park有停车的意思,假设线程为车辆,那么park方法代表着停车,而unpark方...原创 2020-01-20 19:25:00 · 426 阅读 · 0 评论 -
Java并发--读写锁的实现分析
读写状态的设计读写锁同样依赖自定义同步器来实现同步功能,而读写状态就是其同步器的同步状态。回想ReentrantLock中自定义同步器的实现,同步状态表示锁被一个线程重复获取的次数,而读写锁的自定义同步器需要在同步状态(一个整型变量)上维护多个读线程和一个写线程的状态,使得该状态的设计成为读写锁实现的关键。如果在一个整型变量上维护多种状态,就一定需要“按位切割使用”这个变量,读写锁将变量切分成...转载 2020-01-20 19:21:41 · 582 阅读 · 0 评论 -
Java并发--读写锁(ReadWriteLock)
ReadWriteLock读写锁在同一时刻可以允许多个读线程访问,但是在写线程访问时,所有的读线程和其他写线程均被阻塞。读写锁维护了一对锁,一个读锁和一个写锁,通过分离读锁和写锁,使得并发性相比一般的排他锁有了很大提升。除了保证写操作对读操作的可见性以及并发性的提升之外,读写锁能够简化读写交互场景的编程方式。假设在程序中定义一个共享的用作缓存数据结构,它大部分时间提供读服务(例如查询和搜索),...原创 2020-01-20 19:07:57 · 3415 阅读 · 0 评论 -
Java并发--重入锁(ReentrantLock)
重入锁重入锁ReentrantLock,顾名思义,就是支持重进入的锁,它表示该锁能够支持一个线程对资源的重复加锁。除此之外,该锁的还支持获取锁时的公平和非公平性选择。考虑如下场景:当一个线程调用Mutex的lock()方法获取锁之后,如果再次调用lock()方法,则该线程将会被自己所阻塞,原因是Mutex在实现tryAcquire(int acquires)方法时没有考虑占有锁的线程再次获取锁...原创 2020-01-20 18:58:41 · 351 阅读 · 0 评论 -
Java并发--使用AQS自定义同步组件TwinsLock
TwinsLock设计一个同步工具:该工具在同一时刻,只允许至多两个线程同时访问,超过两个线程的访问将被阻塞,我们将这个同步工具命名为TwinsLock。首先,确定访问模式。TwinsLock能够在同一时刻支持多个线程的访问,这显然是共享式访问,因此,需要使用同步器提供的acquireShared(int args)方法等和Shared相关的方法,这就要求TwinsLock必须重写tryAc...原创 2020-01-20 18:47:29 · 407 阅读 · 0 评论 -
Java并发--队列同步器(AQS)的实现分析
同步队列同步器依赖内部的同步队列(一个FIFO双向队列) 来完成同步状态的管理,当前线程获取同步状态失败时,同步器会将当前线程以及等待状态等信息构造成为一个节点(Node)并将其加入同步队列,同时会阻塞当前线程,当同步状态释放时,会把首节点中的线程唤醒,使其再次尝试获取同步状态。同步队列中的节点(Node)用来保存获取同步状态失败的线程引用、等待状态以及前驱和后继节点,节点的属性类型与名称以及...原创 2020-01-20 18:22:19 · 416 阅读 · 0 评论 -
Java并发--队列同步器(AbstractQueuedSynchronizer)
队列同步器(AQS)队列同步器AbstractQueuedSynchronizer(以下简称同步器),是用来构建锁或者其他同步组件的基础框架,它使用了一个int成员变量表示同步状态,通过内置的FIFO队列来完成资源获取线程的排队工作。同步器的主要使用方式是继承,子类通过继承同步器并实现它的抽象方法来管理同步状态,在抽象方法的实现过程中免不了要对同步状态进行更改,这时就需要使用同步器提供的3个方...原创 2020-01-20 17:55:50 · 295 阅读 · 0 评论 -
Java并发--ThreadLocal
ThreadLocalThreadLocal,即线程变量,是一个以ThreadLocal对象为键、任意对象为值的存储结构。这个结构被附带在线程上,也就是说一个线程可以根据一个ThreadLocal对象查询到绑定在这个线程上的一个值。ThreadLocal类中定义了一个静态内部类ThreadLocalMap,每一个Thread中都有一个该类型的变量——threadLocals——用于存储每一个线...原创 2020-01-19 20:52:56 · 498 阅读 · 0 评论 -
Java并发--监视器(monitor)、等待/通知机制
Monitor?Monitor是一种用来实现同步的工具与每个java对象相关联,即每个java对象都有一个Monitor与之对应Monitor是实现Sychronized(内置锁)的基础Monitor的基本结构Owner字段: 初始时为NULL表示当前没有任何线程拥有该monitor record,当线程成功拥有该锁后保存线程唯一标识,当锁被释放时又设置为NULLEntryQ字段...原创 2020-01-19 20:09:53 · 1590 阅读 · 2 评论 -
Java并发--happens-before详解
happens-before的定义JSR-133使用happens-before的概念来指定两个操作之间的执行顺序。由于这两个操作可以在一个线程之内,也可以是在不同线程之间。因此,JMM可以通过happens-before关系向程序员提供跨线程的内存可见性保证(如果A线程的写操作a与B线程的读操作b之间存在happensbefore关系,尽管a操作和b操作在不同的线程中执行,但JMM向程序员保证...原创 2020-01-18 17:21:58 · 1880 阅读 · 0 评论 -
Java并发--concurrent包的实现
concurrent包的实现由于Java的CAS同时具有volatile读和volatile写的内存语义,因此Java线程之间的通信现在有了下面4种方式。A线程写volatile变量,随后B线程读这个volatile变量。A线程写volatile变量,随后B线程用CAS更新这个volatile变量。A线程用CAS更新一个volatile变量,随后B线程用CAS更新这个volatile变...原创 2020-01-18 17:08:18 · 3079 阅读 · 0 评论 -
Java并发--volatile内存语义的实现
volatile内存语义的实现为了实现volatile内存语义,JMM会分别读与写这两种类型的重排序类型。JMM针对编译器制定的volatile重排序规则表如下:举例来说,第三行最后一个单元格的意思是:在程序中,当第一个操作为普通变量的读或写时,如果第二个操作为volatile写,则编译器不能重排序这两个操作。从表我们可以看出:当第二个操作是volatile写时,不管第一个操作是什么,...原创 2020-01-18 17:04:25 · 363 阅读 · 1 评论 -
Java并发--并发编程模型、内存屏障
并发编程模型现代的处理器使用写缓冲区临时保存向内存写入的数据。写缓冲区可以保证指令流水线持续运行,它可以避免由于处理器停顿下来等待向内存写入数据而产生的延迟。同时,通过以批处理的方式刷新写缓冲区,以及合并写缓冲区中对同一内存地址的多次写,减少对内存总线的占用。虽然写缓冲区有这么多好处,**但每个处理器上的写缓冲区,仅仅对它所在的处理器可见。**这个特性会对内存操作的执行顺序产生重要的影响:处理...原创 2020-01-18 16:51:47 · 400 阅读 · 0 评论 -
Java并发--数据依赖性、as-if-aerial、程序顺序规则、重排序对多线程的影响
数据依赖性如果两个操作访问同一个变量,且这两个操作中有一个为写操作,此时这两个操作之间就存在数据依赖性。数据依赖分为下列3种类型:上面3种情况,只要重排序两个操作的执行顺序,程序的执行结果就会被改变。编译器和处理器可能会对操作做重排序。编译器和处理器在重排序时,会遵守数据依赖性,编译器和处理器不会改变存在数据依赖关系的两个操作的执行顺序。这里所说的数据依赖性仅针对单个处理器中执行的指令...原创 2020-01-18 16:33:15 · 836 阅读 · 1 评论