HashMap的环形链表问题
发表于|更新于|Java
|总字数:152|阅读时长:1分钟|浏览量:
- 在JDK1.7的时候,插入链表采用的是头插法,会先将一个需要迁移节点的next指向新位置,然后再将新位置设置成迁移节点。因此在多线程扩容的情况下,一个线程完成了两个节点的迁移,但是被调度到另一个还未完成的线程,就会出现循环链表的情况
- 在JDK1.8,采用了尾插法,只需要遍历一个个节点,挂在tail节点的后面即可,即使迁移过程有并发情况,指针也最多被复制两次
文章作者: cloud_fly
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 cloud_fly blog!
相关推荐
2025-01-11
HashTable和HashMap的区别
区别1、HashMap是线程不安全的,HashTable是线程安全的 HashMap:Fail-fast 机制。表示快速失败,在集合遍历过程中,一旦发现容器中的数据被修改了,会立刻抛出ConcurrentModificationException异常,从而导致遍历失败,像这种情况:定义一个Map集合,使用Iterator迭代器进行数据遍历,在遍历过程中,对集合数据做变更时,就会发生Fail-fast。java.util包下的集合类都是快速失败机制的,...
2025-01-13
从Java线程池到阻塞队列
为什么要用线程池 降低资源消耗:通过重复利用已创建的线程降低线程创建和销毁造成的消耗 提高响应速度:当任务到达时,任务可以不需要等到线程创建就能立即执行 方便管理线程:线程是稀缺资源,如果无条件地创建,不仅会消耗资源,还会降低线程的稳定性,使用线程池可以统一分配、调优和监考 线程池的核心参数 默认线程工厂(省略参数)创建线程池: ThreadPoolExecutor继承自AbstractExecutorService,AbstractExecutorService实现了ExecutorService接口 123456public class Client { public static void main(String[] args) { ThreadPoolExecutor Pool = new ThreadPoolExecutor(8, 8, 2, TimeUnit.SECONDS, new ArrayBlockingQueue<>(4),new...
2025-01-24
CopyOnWriteArrayList
CopyOnWriteArrayList是Java并发包中提供的一个并发容器,它是个线程安全且读操作无锁的ArrayList,写操作则通过创建底层数组的新副本来实现,是一种读写分离的并发策略,我们也可以称这种容器为”写时复制器”,Java并发包中类似的容器还有CopyOnWriteSet 原理 初始化时候,CopyOnWriteArrayList内部维护了一个可变数组,用于存储元素 修改的时候,首先将当前容器复制一份,然后在新副本上执行写操作,结束之后再将原容器的引用指向新容器 读操作直接在原数组上进行,因为读操作不会改变数据,所以读操作不会加锁 优点 我们可以对CopyOnWriteArrayList并发的读,而不需要加锁,采用了读写分离的思想,读和写不同的容器 缺点 内存占用问题:因为CopyOnWriteArrayList的写时复制机制,在写的时候,内存中会出现两个对象的内存,旧的对象和新写入的对象,可能会造成频繁的young gc和full...
2025-01-20
JUC同步工具CountDownLatch源码解析,与CyclicBarrier的对比
基本使用CountDownLatch典型用法:某一线程在开始运行前等待n个任务线程数执行完毕。将CountDownLatch的计数器初始化为new CountDownLatch(n),每当一个任务线程数执行完毕,就将计数器减1 countdownLatch.countDown(),当计数器的值变为0时,在CountDownLatch上await()的线程就会被唤醒。一个典型应用场景就是启动一个服务时,主线程需要等待多个组件加载完毕,之后再继续执行 自定义任务类 1234567891011121314151617181920212223242526package org.example; import java.util.Random;import java.util.concurrent.CountDownLatch; public class Task implements Runnable{ private final static Random random = new Random(); private Integer id; ...
2025-01-18
Java线程安全问题
Java线程安全性问题 原子性:一个或多个线程操作 CPU 执行的过程中被中断,互斥性称为操作的原子性 可见性:一个线程对共享变量的修改,其他线程不能立刻看到。要保证一个线程对主内存的修改可以及时的被其他线程观察到 有序性:程序执行的顺序没有按照代码的先后顺序执行 原子性安全JDK 里面提供了很多 atomic 类,比如 AtomicInteger、AtomicLong、AtomicBoolean 等等,这些类本身可以通过 CAS 来保证操作的原子性。另外 Java 也提供了各种锁机制,来保证锁内的代码块在同一时刻只能有一个线程执行,比如使用 synchronized 加锁,保证一个线程在对资源进行读、写时,其他线程不可对此资源进行操作,从而保证了线程的安全性 可见性安全同样可以通过 synchronized 关键字加锁来解决,与此同时,java 还提供了 volatile 关键字,要优于 synchronized 的性能,同样可以保证修改对其他线程的可见性。volatile...
2025-01-20
Java信号量——Semaphore
基本概念Semaphore是一个计数信号量,它可以用来控制对某一资源的访问数量。在Java中,Semaphore位于java.util.concurrent包中 Semaphore的用途流量控制:Semaphore可以用来控制同时访问特定资源的线程数量,例如数据库连接、文件句柄等分配资源:Semaphore可以用来分配有限数量的资源,例如线程池、线程队列等 Semaphore的使用技巧 创建Semaphore 1Semaphore semaphore = new Semaphore(5); 获取信号量 1semaphore.acquire(); 请求一个信号量,这时候的信号量个数-1(是尝试获取,如果是>0就减去, 否则阻塞等待信号量>0) 释放信号量 1semaphore.release(); 信号量+1 使用tryAcquire方法 1boolean acquired = semaphore.tryAcquire(); 上述代码尝试获取信号量,如果成功则返回true,否则返回false 使用tryAcquire(long...
公告
欢迎加入郑州大学ACM交流群 QQ群562888278,一起学习