One Trick Per Day

简介: Map初始化应避免容量设置不当,建议用Guava指定预期大小;禁用Executors创建线程池,防止OOM,推荐手动定义参数或使用Guava;Arrays.asList返回不可变集合,禁止修改操作;遍历Map优先使用entrySet或forEach提升性能;SimpleDateFormat非线程安全,禁用static修饰,推荐ThreadLocal或Java8新时间类;并发修改记录需加锁,优先乐观锁(version控制),冲突低时重试不少于3次。

1.初始化Map大小并非用多少指定多少
初始化Map并非用多少初始化Size是多少,建议使用Guava,避免扩容引起的动荡()
说明
如:Map map = new HashMap<>(1); 在具体使用时,并非size=1,而是最近的2的幂等,如1实际是2,3实际是4,9实际是16
使用方法
依赖gvaua:Map map = Maps.newHashMapWithExpectedSize(7);
手动声明:Map map = new HashMap<>(实际存储个数 / 0.75 + 1);
2.线程池初始化严禁使用Executors
使用线程池时候,我们可能会使用下面四个场景,这在alibaba代码规范中都是明令禁止的
我们先来一个简单的例子,模拟一下使用 Executors 导致 OOM 的情况。
通过指定 JVM 参数:-Xmx8m -Xms8m 运行以上代码,会抛出 OOM:
以上代码指出,ExecutorsDemo.java 的第 16 行,就是代码中的 executor.execute(new SubThread());。
通过上面的例子,我们知道了 Executors 创建的线程池存在 OOM 的风险,那么到底是什么原因导致的呢?我们需要深入 Executors 的源码来分析一下。其实,在上面的报错信息中,我们是可以看出蛛丝马迹的,在以上的代码中其实已经说了,真正的导致 OOM 的其实是 LinkedBlockingQueue.offer 方法。
如果读者翻看代码的话,也可以发现,其实底层确实是通过 LinkedBlockingQueue 实现的:
如果读者对 Java 中的阻塞队列有所了解的话,看到这里或许就能够明白原因了。Java 中 的 BlockingQueue 主 要 有 两 种 实 现, 分 别 是 ArrayBlockingQueue 和 LinkedBlockingQueue。ArrayBlockingQueue 是一个用数组实现的有界阻塞队列,必须设置容量。LinkedBlockingQueue 是一个用链表实现的有界阻塞队列,容量可以选择进行设置,不设置的话,将是一个无边界的阻塞队列,最大长度为 Integer.MAX_VALUE。这里的问题就出在:不设置的话,将是一个无边界的阻塞队列,最大长度为Integer.MAX_VALUE。也就是说,如果我们不设置 LinkedBlockingQueue 的容量的话,其默认容量将会是 Integer.MAX_VALUE。 而 newFixedThreadPool 中创建 LinkedBlockingQueue 时,并未指定容量。此时,LinkedBlockingQueue 就是一个无边界队列,对于一个无边界队列来说,是可以不断的向队列中加入任务的,这种情况下就有可能因为任务过多而导致内存溢出问题。上面提到的问题主要体现在 newFixedThreadPool 和 newSingleThreadExecutor 两个工厂方法上,并不是说newCachedThreadPool 和 newScheduledThreadPool 这两个方法就安全了,这两种方式创建的最大线程数可能是Integer.MAX_VALUE,而创建这么多线程,必然就有可能导致 OOM
正确使用:
这种情况下,一旦提交的线程数超过当前可用线程数时,就会抛出java.util.concurrent.RejectedExecutionException,这是因为当前线程池使用的队列是有边界队列,队列已经满了便无法继续处理新的请求。但是异常(Exception)总比发生错误(Error)要好。
但是部分alibaba作者更推荐使用guava创建对应的线程池,示例如下:
通过上述方式创建线程时,不仅可以避免 OOM 的问题,还可以自定义线程名称,更加方便的出错的时候溯源。
3.Arrays.asList之后不要调用修改操作
因为asList返回的实际是一个Arrays内部类,并没有实现集合的修改方法(add/remove/clear)// 当操作修改方法时,会报UnsupportedOperationException。
第一种情况:list.add("yangguanbao"); 运行时异常。
第二种情况:str[0] = "gujin"; 那么 list.get(0)也会随之修改。[涉及栈堆指针操作,修改数组的数据,导致同样引用该数据的list值被改变]
4.使用 entrySet 遍历 Map 类集合 KV
说明:keySet 其实是遍历了 2 次,一次是转为 Iterator 对象,另一次是从 hashMap 中取出key 所对应的 value。而 entrySet 只是遍历了一次就把 key 和 value 都放到了 entry 中,效率更高。
如果是 JDK8,使用 Map.foreach 方法。
正例:values()返回的是 V 值集合,是一个 list 集合对象;keySet()返回的是 K 值集合,是一个 Set 集合对象;entrySet()返回的是 K-V 值组合集合。
5.SimpleDateFormat不要定义为static
SimpleDateFormat 是线程不安全的类,一般不要定义为 static 变量,如果定义为static,必须加锁,或者使用 DateUtils 工具类。
正例:注意线程安全,使用 DateUtils。亦推荐如下处理:
Java
运行代码
复制代码
1
2
3
4
5
6
private static final ThreadLocal df = new ThreadLocal() {
@Override
protected DateFormat initialValue() {
return new SimpleDateFormat("yyyy-MM-dd");
}
};
说明:如果是 JDK8 的应用,可以使用 Instant 代替 Date,LocalDateTime 代替 Calendar,DateTimeFormatter 代替 SimpleDateFormat,官方给出的解释:simple beautiful strong immutable thread-safe。
6.并发修改同一记录时需要加锁
要么在应用层加锁,要么在缓存加锁,要么在数据库层使用乐观锁,使用 version 作为更新依据。
说明:如果每次访问冲突概率小于 20%,推荐使用乐观锁,否则使用悲观锁。乐观锁的重试次数不得小于 3 次

相关文章
|
1天前
|
机器学习/深度学习 存储 边缘计算
物联网平台实战:从设备接入到数据分析的端到端架构演进
本文系统阐述物联网平台从设备接入到数据分析的架构演进路径,涵盖多协议接入、边缘计算、实时处理与AI集成等关键技术,分享高并发优化、分层存储、安全认证等实战经验,助力企业构建高效、可扩展的IoT平台,推动数字化转型与智能决策。
|
1天前
|
Java API Maven
[MES]不合格订单接入提醒功能(☆☆☆)
克隆或下载代码至IDEA,配置JDK、Maven等环境,遇问题主动请教同事或组长。运行项目后,针对“不合格工单超30分钟需通知”需求,结合定时任务与短信/钉钉API实现。涉及Git、Maven、SpringBoot技术。
|
1天前
|
消息中间件 物联网 测试技术
幂等方案专题
适用于科技公司服务器及物联网设备异常时的语音告警通知。开通语音服务后,可申请资质、话术与模板,支持变量替换,通过API调用实现自动拨打电话播报告警内容,并可通过控制台或API查询呼叫记录,支持消息回执推送,保障告警及时处理。
|
1天前
|
机器学习/深度学习 存储 边缘计算
物联网平台实战:从设备接入到数据分析的端到端架构演进
本文详解物联网平台从设备接入到数据分析的架构演进路径,涵盖多协议接入、边缘计算、实时处理与AI集成等核心技术,分享高并发优化、分层存储、安全认证等实战经验,助力企业构建高效、可扩展的IoT系统,推动数字化转型与智能决策升级。(238字)
|
1天前
|
供应链 监控 安全
区块链BaaS应用:利用阿里云平台快速发行和管理数字资产
阿里云区块链服务(BaaS)助力企业高效构建数字资产平台,支持多链部署、智能合约开发与全生命周期管理。涵盖发行、交易、清算及审计追溯,适用于数字藏品、积分通证、供应链金融等场景,提供安全合规、弹性可扩展的一站式解决方案。
|
1天前
|
弹性计算 运维 安全
自动化运维实战:利用运维编排OOS批量管理数百台ECS
阿里云运维编排服务(OOS)助力企业高效管理大规模ECS集群,支持批量操作、任务编排、定时执行与安全管控,实现运维自动化。相比传统人工操作,效率提升超95%,显著降低错误率,构建标准化、可复用的智能运维体系。
|
1天前
|
测试技术
发布模式
蓝绿部署是一种减少发布中断的策略,通过维护两套系统(绿为线上,蓝为新版本)实现快速切换与回滚。金丝雀发布则逐步替换旧系统,适用于大规模集群。A/B测试用于比较不同版本效果,非发布策略。三者各有适用场景。
|
1天前
|
弹性计算 运维 监控
混合云降本之道:通过CEN连接IDC与云上弹性资源
阿里云CEN助力企业构建高性价比混合云,打通IDC与云端资源,实现弹性扩展、智能调度与成本优化。通过专线互联、自动扩缩容和统一管理,显著降低硬件、网络与运维成本,广泛适用于电商、金融等场景,成为数字化转型主流选择。(238字)
|
1天前
|
存储 缓存 监控
EFC&CTO:缓存引发数据不一致问题排查与深度解析
EFC客户端更新缓存架构后,在NAS场景CTO测试中出现data mismatch。经排查,因分布式缓存版本号回退,导致旧NULL数据被读入pagecache并刷入文件系统,破坏了正常数据。通过维护递增版本号修复,最终测试通过。
|
1天前
|
弹性计算 安全 Serverless
预留实例券 vs 节省计划:哪种计费方式更适合你的业务?
企业云成本如何从“可变”转为“可控”?阿里云预留实例券(RI)与节省计划(SP)是两大利器。RI适合长期稳定业务,折扣高但灵活性低;SP覆盖广、管理简单,适配弹性多变场景。本文通过四维对比与决策树,助您按业务特性选择最优方案,实现成本从消耗到战略投资的转变。(238字)