![](https://img-blog.csdnimg.cn/20201014180756928.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
Java多线程
文章平均质量分 52
ChaosKong
既要低头做事,又要抬头看天。
展开
-
Java锁源码分析-ReentrantReadWriteLock(可重入的读写锁)
Java锁源码分析-ReentrantReadWriteLock(可重入的读写锁)使用场景基本用法KaTeX数学公式 本文分析了可重入的读写锁的使用场景,基本用法,源码解析。 使用场景 首先了解下读锁与写锁的互斥性: 读锁-读锁 不互斥 读锁-写锁 互斥 写锁-写锁 互斥 也就是说在多个线程都加读锁,不存在写锁的情况下,多个线程可以并发执行下去。这样,就解决了传统上的直接加互斥锁,导致不管是读-读,还是读-写都要等待持有锁的线程释放锁。使用读写锁在合适的场景下(一般是读的次数远高于写的次数)就可以提高并原创 2021-03-05 11:28:21 · 225 阅读 · 2 评论 -
Java JUC包源码分析 - 多阶段任务Phaser
Phaser是jdk1.7才出现的,可以实现分阶段实现任务,多个线程执行第一个阶段任务,等待所有线程第一阶段执行完了才开始执行第二阶段,如此类推。其实就是多个栅栏CyclicBarrier,只不过这个Phaser比较灵活。 先看下用法: 上个例子写的不够贴切,再深入理解一下再写。。。。。。。 package com.pzx.test.test002; import java.text.Si...原创 2018-09-21 23:02:29 · 354 阅读 · 0 评论 -
Java JUC包源码分析 - ArrayBlockingQueue
ArrayBlockingQueue是线程安全的阻塞队列,底层是基于数组实现的,既然是数组,那肯定是有界的。 保证线程安全是通过可重入锁ReentrantLock实现,且可以控制是公平锁还是非公平锁 另外,还提供了Condition条件还控制队列的空和满。当插入一个元素进去,发现队列满了,就会调用notFull.await(),取走一个元素的时候,就会调用notFull.signal()唤醒插...原创 2018-09-15 12:08:17 · 124 阅读 · 0 评论 -
Java JUC包源码分析 - ConcurrentHashMap
ConcurrentHashMap之较于HashMap是保证了线程安全,其实现方式之精妙有很多值得学习的地方。同时,这篇文章也将持续更新,毕竟目前只研究了常用的几个操作,还有其他操作,等待我去深挖。 ConcurrentHashMap主要是依靠了CAS无锁算法和对操作的数组索引处的头节点加锁。 扩容操作是可以多线程协助进行,线程只要检测到在扩容就放下当前工作去协助扩容,扩容的优先级还挺高!毕竟...原创 2018-09-14 22:48:03 · 206 阅读 · 0 评论 -
Java JUC包源码分析 - 倒计时器CountDownLatch
倒计时器CountDownLatch是让一个或多个线程等待其他的线程执行完后再开始继续执行,是基于共享锁实现的。 话不多说,先看下怎么使用,下面是自己写的一个Demo package com.pzx.test004; import java.text.SimpleDateFormat; import java.util.Date; import java.util.concurrent.C...原创 2018-09-11 11:34:38 · 226 阅读 · 0 评论 -
Java JUC包源码分析 - 线程池ThreadPoolExecutor
线程池的相关类结构 线程池就是存储了已创建指定个数的线程的集合,当需要用线程执行任务的时候,就可以从线程池中拿一个空闲的线程来执行任务。先看下源码,源码分析完了再看线程池的周边应用,以及几个思考。 第一部分,先看下线程池的结构,然后是如何创建线程池。 第二部分,线程池的状态 第三部分,提交任务到线程池的方法 第四部分,关闭线程池 第五部分,拒绝策略 第一部分: pub...原创 2018-09-18 00:20:06 · 233 阅读 · 0 评论 -
Java JUC包源码分析 - CopyOnWriteArrayList和CopyOnWriteArraySet
CopyOnWriteArrayList可以看作是线程安全的ArrayList,底层数据结构是数组。主要实现过程就像它的名字,在写(增、删、改)的时候,先copy出一份副本,然后对副本操作,最后把副本赋值给原来的数组,整个过程是在ReentrantLock的lock下完成。 这么做的目的其实就是为了在保证线程安全的情况下,不阻塞读。 存储数据的是用volatile修饰的数组,能够保证多线程场景...原创 2018-09-12 19:35:47 · 188 阅读 · 0 评论 -
Java锁源码分析-ReentrantLock和AQS
ReentrantLock与synchronized都是可重入锁,都是独占锁。 可重入锁的意思就是在一个已获得锁的线程中,可以再次获得同一把锁。 区别在于: 1、ReentrantLock可以设置锁等待的超时时间(避免一致等待下去) 2、ReentrantLock可以实现公平锁与非公平锁(阻塞线程是否按照先来先获得锁的顺序) 3、ReentrantLock可以设置条件(Condition...原创 2018-09-07 00:11:47 · 216 阅读 · 0 评论 -
Java JUC包源码分析 - ConcurrentLinkedQueue
ConcurrentLinkedQueue不同于LinkedBlockingQueue,它没有利用ReentranLock以及Condition条件。而是利用死循环+CAS来实现线程安全,也就是一个重试的机制。 ConcurrentLinkedQueue是一个无阻塞的高效的队列。 ConcurrentLinkedQueue是基于单向链表的。 public class ConcurrentL...原创 2018-09-16 23:52:54 · 161 阅读 · 0 评论 -
Java JUC包源码分析 - LinkedBlockingDueue
LinkedBlockingDueue是基于一个双向的链表,可以先进先出(队列),也可以先进后出 (栈) 不允许插入null,基本原理和方法都和LinkedBlockingQueue差不多 public class LinkedBlockingDeque<E> extends AbstractQueue<E> implements BlockingDe...原创 2018-09-16 22:47:28 · 325 阅读 · 0 评论 -
Java JUC包源码分析 - LinkedBlockingQueue
LinkedBlockingQueue是一个单向链表的阻塞队列,头部和尾部分别有一个可重入锁控制写入和读取,并且两个锁还各自带了一个condition条件。这样可以增加并发度。 这也可以看作是一个可用在队列两端同时操作的队列 put()和take()方法都是当遇到满了或空了条件会阻塞的方法 offer()和poll()方法都是当遇到满了或空了直接返回false;或者是传入一个等到时间的参数。...原创 2018-09-16 14:31:16 · 165 阅读 · 0 评论 -
Java多线程-线程基本方法
上面是线程状态的转换图 yield: yield使得当前线程的运行状态由 运行状态转为就绪状态 在当前线程获得锁的情况下,不释放锁 Object的wait()是使得当前线程的运行状态由 运行状态转为阻塞状态 在当前线程获得锁的情况下,wait释放锁 sleep();使得当前线程休眠指定时间(大于等于?) 在当前线程获得锁的情况下,不释放锁 join();让主线程等待子线程执行完毕再执行...原创 2018-09-04 00:13:56 · 130 阅读 · 0 评论 -
Java多线程-线程基础
线程的两种实现方式: 继承Thread(Thread类也实现了Runnable接口) 实现Runnable接口 synchronized: 只要synchronied()是同一把锁,那么多线程访问的时候就会阻塞 注意:对象锁和类锁是属于不同的锁,所以可以同时访问 类锁: private static synchronized void b() {} 对象锁:private synchroni...原创 2018-09-04 00:00:48 · 102 阅读 · 0 评论 -
Java JUC包源码分析 - 信号量Semaphore
信号量是基于共享锁和许可的原理实现,在初始时给定许可数,获取时如果当前许可足够,就获得许可往下执行,否则就阻塞。 信号量还分公平信号量和非公平信号量,两者的区别就在于再尝试获取许可的时候,公平信号量还需要判断当前线程所在的节点是不是CLH队列的头节点,其他都一样。释放锁的过程两者也是一样的。 先看下用法: package com.pzx.test.test00001; import ja...原创 2018-09-11 23:21:31 · 371 阅读 · 0 评论 -
Java JUC包源码分析 - 栅栏CyclicBarrier
栅栏不同于倒计时器的一点是倒计时器是一个或N个线程等待其他线程调用countdown()到指定次数后再继续执行,而栅栏是N个线程之间互相等待,当调用await()到达指定次数后就会唤醒所有等待线程,同时还可以在到达指定数量时触发一个定制的动作(Runnable,由最后一个调用await()方法并唤醒所有线程的那个线程执行)。另外栅栏是可以循环使用的。 栅栏的实现方式是独占锁+Condition条...原创 2018-09-11 19:33:10 · 482 阅读 · 0 评论