![](https://img-blog.csdnimg.cn/20201014180756923.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
java源码
文章平均质量分 83
竹下星空
这个作者很懒,什么都没留下…
展开
-
CountDownLatch、CyclicBarrier、semaphore
CountDownLatch中调用await方法线程需要等待所有调用countDown方法的线程执行,这就很适合一个业务需要一些准备条件,等准备条件准备好之后再继续执行,如果一些复杂的聚合查询,还有一些类似于广播消息的功能。原创 2022-09-13 14:53:59 · 1386 阅读 · 0 评论 -
ThreadLocal
ThreadLocal实际上是通过Thread的成员变量threadLocals来发挥作用,ThreadLocal对象作为key,设置的值作为value放入threadLocals中,所以你如果使用了ThreadLocal那么当前线程就会使用threadLocals变量持有你设置值的threadlocal对象和这个threadLocal设置的值当你用threadLocal对象get方法获取值时就会通过threadLocals变量的map获取这个threadLocal设置的值。原创 2022-09-13 10:35:15 · 238 阅读 · 0 评论 -
reentrantLock
重入的概念是什么,实现原理是什么?公平锁和非公平锁区别是什么,体现在哪些地方?没有竞争到锁的线程怎么实现等待,释放锁时又是怎么被唤醒的?发现没有是不是跟synchronized代码结构差不多,只是多了一个lock和unlock的过程。我们先画个图来对比一下synchronized和lock的数据结构:这就是学技术特别有趣的地方,你看多了感觉很多高大上的技术底层设计实际都差不多。ReentrantLock默认是非公平锁。原创 2022-09-14 13:45:07 · 433 阅读 · 0 评论 -
scheduledThreadPool
怎样做到每个任务延迟指定时间执行?内部使用了什么数据结构保存延迟任务?延迟任务放入scheduledThreadPool时机并不固定,怎么保证按延迟时间顺序执行?原创 2022-09-12 16:29:41 · 508 阅读 · 0 评论 -
CachedThreadPool
corePoolSize是0,maximumPoolSize是Integer.MAX_VALUE,根据我们之前对源码的分析,CachedThreadPool不会有核心线程,核心线程数的addworker方法不会执行,直接尝试加入queue中。keepAliveTime是60s,也就是60s从队列中没有拿到任务,worker就会自动销毁,销毁过程在fixed的分析中已经看过了。原创 2022-09-12 16:08:41 · 2711 阅读 · 0 评论 -
FixedThreadPool
newFixedThreadPool实际上返回的是ThreadPoolExecutor,ThreadPoolExecutor实际就是线程池实现类,使用了典型的模板方法设计模式,通过ThreadPoolExecutor构造器的说明我们稍微解释一下各参数的意思:corePoolSize 核心线程数,线程池一直存在的线程(即使这些线程是空闲的),除非你设置allowCoreThreadTimeOut。原创 2022-09-12 15:50:44 · 3276 阅读 · 0 评论 -
ArrayBlockingQueue
记得LinkedBlockingQueue使用的AtomiInteger,而这里直接使用了int,这是因为LinkedBlockingQueue使用的两把锁,put和take互不干扰,所以count有多线程操作,而ArrayBlockingQueue使用的是一把锁,put和take互斥。说明元素此时已经放过数组一轮的位置了,而且通过之前的判断,现在元素的数量是没有达到数组长度的,所以数组前面的元素肯定有被take的,所以此时应该重新开始放元素。同一个作者写的,为什么会写出两个逻辑,不是很理解。原创 2022-09-12 15:32:08 · 466 阅读 · 0 评论 -
ConcurrentHashMap解析
在初始化数组时使用cas保证只有一个线程能成功并去做初始化工作,其他线程则继续for循环在没有hash冲突时tab[i]使用cas进行赋值,保证同时只有一个线程赋值成功,其他线程则在下次for循环时进入hash冲突的代码段当有hash冲突时使用synchronized锁住tab[i]位置的元素,而且进行了双检查,保证上锁后元素没有变化,然后在锁里进行链表或红黑树的维护,保证了hash冲突时元素的插入也是线程安全的。原创 2022-09-12 15:30:21 · 343 阅读 · 0 评论 -
ConcurrentLinkedQueue解析
add过程实际就是不停就是在单链表不断挂新元素的过程,挂next元素时使用了cas来保证线程的安全性,而且不是每次add都会移动tail指针,而是tail已经不是现在的最后一个node时才会移动tail指针。原创 2022-09-12 15:04:53 · 7155 阅读 · 1 评论 -
LinkedBlockingQueue源码分析
在put元素时,首先拿到的putLock重入锁,而且记录元素个数的count也是AtomicInteger,保证了count累加的线程安全性LinkedBlockingQueue的node节点、head、tail,next等都没有使用volatile修饰,而且挂新节点也没有ConcurrentLinkedQueue那么复杂的自旋和判断,所以这就是锁带来的一个好处(或者说是锁粒度带来的好处,粒度越小可能存在的线程安全问题越多),代码复杂度会大大降低,各种多线程下写失败的情况就不会出现,原创 2022-09-12 11:38:47 · 112 阅读 · 0 评论 -
TreeMap和LinkedHashMap
底层是基于红黑树实现,是个有序集合,按照key的compareTo方法或在构造时传入的Comparator比较器进行排序。这里需要注意如果在构造 时没有传入Comparator,那么key必须实现Comparable接口,不然会报错TreeMap是通过Comparator比较器来构建红黑树从而保证key的有序性,而LinkedHashMap是通过双向链表来保证元素插入的有序性,两者有序性的含义不是一样的。原创 2022-09-12 11:18:34 · 1755 阅读 · 0 评论 -
HashMap的put源码解析
hashMap的put方法解析原创 2022-09-12 10:57:14 · 165 阅读 · 0 评论 -
HashMap源码面试题
总体特点:java1.8之前使用的是数组+单向链表的数据结构,java1.8及之后使用的是数组+单向链表+红黑树的数据结构,在hash冲突形成的单向链表元素个数达到8个时会转成红黑树。使用无参构造器初始化的node数组容量是16(在resize()方法中初始化),加载因子是0.75(也就是说当node数组中元素超过0.75容量时会进行扩容),扩容时新容量是旧容量的2倍。扩容时java1.8之前使用的头插法,头插法可能会导致元素的丢失、hash环等问题,java1.8及之后使用的是尾插法,能够避免之前原创 2022-04-05 13:42:50 · 582 阅读 · 0 评论 -
java源码之LinkedList
LinkedList优点:基于双向链表实现,增删改的效率很高可以当队列来用LinkedList缺点:链表的遍历时间复杂度是O(n),所以随机读是非常慢的LinkedList使用场景:LinkedList在生产中使用较ArrayList少很多,因为一般程序都是读多写少,LinkedList却更适合写多读少的情况。LinkedList主要方法解析:add(E e):在双向链表尾部插入一个元素生成指针l指向双向链表中的最后一个元素last生成一个新的node节点,pre是last,next是原创 2022-04-04 17:22:59 · 428 阅读 · 0 评论 -
ArrayList源码
ArrayList优点:随机读性能很高,因为底层是基于数组实现,可以通过get(i)寻址快速读取获取元素个数性能很高arrayLis天生按元素插入顺序排序ArrayList缺点:在扩容时需要从旧数组把元素拷贝到新数组,性能很差在随机插入时会导致插入点之后的元素在数组中移动,性能也很差ArrayList使用场景及使用注意事项:在new ArrayList时最好根据业务场景进行容量的初始化,避免在之后的Add操作时触发数组的扩容,进而提高使用性能如果有频繁的add(i,e)的操作则不建议使用原创 2022-04-04 15:57:08 · 516 阅读 · 0 评论