Java8中DateTimeFormatter真的是线程安全的吗?

news2024/12/22 20:40:29

文章目录

    • @[toc]
  • 1.背景
  • 2.解决办法
    • 2.1办法一:换姿势或者升级JDK的版本
    • 2.1办法二:更换文件名称字生成策略

Java8中DateTimeFormatter真的是线程安全的吗?

答案是否定的

1.背景

  由于之前写了一个旷世的ocr的服务,接入了旷世的FaceID的人脸比对的接口,然后就在写代码的过程中就遇到了这个奇怪的bug,旷世的FaceId的人脸识别的接口文档如下:

https://faceid.com/document/faceid-guide-docs/v5_get_result

  说实话,旷世的产品真的是太难用了,光说这个接口接入后端也没有一个像样的SDK还得自己去写http各种封装接口、参数和解析返回结果,代码量有点的,用起来不像大厂的产品,都是给一个SDK,给使用者降低了接入的门槛有降低、接入的效率有提高和产品的质量也是没有啥缺陷的,相关的ocr的产品比如说是识别新能源和油车的车牌驾驶证还是行驶证上的车牌新能源比油车多一位就识别不出来,这个问题提给他们,他们也修复不了,以后的版本在修复,还是我们做了业务调整处理了这个识别不了的问题,还有就是副页相关的识别也是识别不出来,比起阿里的ocr来说,只能说是一个天上的一个地下,然后我就写了一段代码如下:

DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
String fileName = dtf.format(LocalDateTime.now());

  这段代码是在一个工具类的静态方法中用于解析base64的图片(这里的业务是活体检测返回最好的一张人脸照片)和拉取Oss临时身份证正面的图片URL文件到本地,然后调用旷世的接口需要这两个图片作为参数调用人脸比对的接口,活体检测和人脸比对的大体流程简单的说下:

  1.接口授权认证(接口的加解密和参数的签名验签啥的,appkey,secret,)

  2.前端请求业务后端获取biz_token,然后前端的sdk拿着这个biz_token唤醒相机进行活体检测,活体检测会采集一张人脸的最好的一张base64的图片

  3.最后一步就是去调用业务后端封装的一个活体检测和人脸比对的接口,该接口里面做了两件事情:

  第一点:根据前端传来的biz_token去调用旷世的获取活体检测结果的接口,然后解析返回结果
  第二点:根据前端传来的oss的 身份证(ocr识别传到oss上的临时身份证URL)的参数解析为本地的file2,然后根据第一点返回来的最好了的一张活体检测采集到的最好的一张人脸base64的图片解析为本的文件file2,就是这两个文件的解析,调用了同一个工具类的方法,该方法里面写了上面那段神仙代码,然后生成的file1和file2的名字都会有概率是相同的,然后传到旷世那边,找他们排查对接,他们说我们这边穿过去的这两个文件的MD5的值是一样的,瞬间我就感到了不不可思议,于是乎,疯狂review自己的代码和看旷世的接口文档,调整各种姿势修改代码调试和那边对接,那边排查的结果始终是两个文件的MD5值是相同的,最后在一番修改和调试后发现本地生成的文件的名字是一样的并且把两个文件在解析到本地的文件的MD5的值打印出来了,调用旷世的时候又把两个文件对应的MD5的值打印出来了:

// 打印文件的MD5代码
//DigestUtils.md5Hex() 这个方法是这个包里面的 package org.apache.commons.codec.digest;
FileInputStream fis1 = new FileInputStream(xxx); // xxx是传入的File
String idCardMD5 = DigestUtils.md5Hex(fis1);

在这里插入图片描述

  经过一番调试和观察以后还以为是流没有关闭导致文件被占用两个文件的引用都指向同一个对象的地址导致的或者是两个文件的复制搞错了,结果发现两个文件在生成名字的时候会有一定的打概率生成的是相同的名字,这样两调用的地方就拿到的是同一个文件,也就是两个调用的地方指向了这个名字相同的文件导致最后两个文件的MD5的值一样了,两个文件的MD5的值一样就导致身份证的本地图片解析被活体检测采集到的最好的一张照片覆盖了,这种就相当于活体检测的人脸跟活体检测的人脸比对通过,而不是身份证照片和活体检测采集到的最好的一张人脸图片作比对,跟我们的预期不符合了,我们的预期是只有活体检测结果通过并且人脸比对身份证正面照片和活体检测采集的最好的一张图片比对成功,都是通一个人刷脸的操作而不是登录的ocr身份证认证通过的账号和刷脸不是通一个人的这种操作,给我搞了一下午到晚上9点多,把这个问题记录复盘,也是奇葩问题遇到的多,解决的也是那么酸爽的,废话不多说,接下来看如何解决吧。

2.解决办法

2.1办法一:换姿势或者升级JDK的版本

  升级JDK的版本在这里就不采用这种方式了,采用更换姿势的方式

  换姿势代码如下:

private static final DateTimeFormatter dtf = new DateTimeFormatterBuilder().appendPattern("yyyyMMddHHmmss").appendValue(ChronoField.MILLI_OF_SECOND, 3).toFormatter();
//格式化的地方使用这个全局df来格式化
String fileName = df.format(LocalDateTime.now());

  在网上看到了一篇文章,链接如下:

https://zhuanlan.zhihu.com/p/144372694

  这篇文章说Jdk8 DateTimeFormatter 解析 yyyyMMddHHmmssSSS 有问题,然后我就类比猜测了下:Jdk8 DateTimeFormatter 解析 yyyyMMddHHmmss也是有问题的,结果用上面的姿势证明它确实是有bug的,所以以后在回答和使用这个Jdk8 DateTimeFormatter的时候就不能说这个Jdk8 DateTimeFormatter类一定是线程安全的了,这个例子就是一个很好的坑,这个问题在Jdk9中修复,在jdk9及其以上的版本有没有修复,这个可以去官方找或者,升级下jdk试下就知道了,具体jdk8的DateTimeFormatter在解析yyyyMMddHHmmssSSS和yyyyMMddHHmmss格式的时候为啥会有bug?这个问题就不去深究了,根据上面正确的姿势来看估计跟解析格式的精度或者是缓存啥的有关系的。

2.1办法二:更换文件名称字生成策略

  使用其它方式生成唯一的文件名字,可以使用UUID、美团的Leaf、雪花算法(这个也会重复的,就拿mybatisPlus的id生成器来说,默认使用的是雪花算法,会有一定的重复的,所以需要设置机房id(datacenter-id)和work-id),自定义使用时间戳字符串在加随机字符啥的,或者是自己写个分布式ID生成的算法等等,方法还很多的,这里就不在啰嗦了

# mybatisPlus的id生成器来说,默认使用的是雪花算法 防止id生成重复的配置如下:
mybatis-plus:
  mapper-locations: classpath*:/mapper/*.xml
  type-aliases-package: com.xxxx.entity
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  global-config:
    datacenter-id: ${random.int(1,31)}
    worker-id: ${random.int(1,31)}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/494175.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

初识WebAssembly

WebAssembly是一种新型的低级字节码格式,它可以在现代的浏览器中运行,同时也支持其它的平台,例如Node.js、Web Worker等。WebAssembly的目标是在Web平台上提供一种高效、安全、可移植的运行时环境,可以被用于执行任意类型的二进制…

ChatGPT实现leetcode 刷题和变型

leetcode 刷题和变型 作为一个程序员,Leetcode 是一个非常重要的网站。它不仅可以帮助程序员提高算法和数据结构的能力,还能帮助我们准备技术面试。但是,刷 Leetcode 也需要花费大量的时间和精力来解决各种难题。那么,有没有什么…

达成事务条件的实现原理

事务存在的意义:保证系统中的数据,都是符合预期的;相互关联的数据之间,不会产生矛盾 达成事务的条件 原子性:一个操作,要么同时成功、要么同时失败 隔离性:各业务,读写相互独立 持…

arm 源码编译kernel 对比image zimage uimage vmlinux

一 源码编译kernel 下载交叉编译工具链 下载cc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf.tar.xz ,这是官网的。使用下面命令下载。 585 wget https://releases.linaro.org/components/toolchain/binaries/4.9-2017.01/arm-linux-gnueabihf/gcc-linaro-4.9…

每天一道算法练习题--Day22 第一章 --算法专题 --- ----------最大公约数

关于最大公约数有专门的研究。 而在 LeetCode 中虽然没有直接让你求解最大公约数的题目。但是却有一些间接需要你求解最大公约数的题目。 如何求最大公约数? 定义法 def GCD(a: int, b: int) -> int:smaller min(a, b)while smaller:if a % smaller 0 and b …

一个集团企业,如何从0到1构建信息化系统?

当今时代,信息技术已经成为企业发展不可或缺的一部分,特别是对于一个大型集团公司来说,如何构建一个高效的信息化系统对于其业务发展至关重要。 我们想要构建一个优质高效的信息化系统,首先需要了解现在大的趋势是怎样的。 目前…

【Linux】Linux安装Java环境(OpenJDK)

文章目录 第一步:第二步,选择合适的版本安装:第四步,配置环境变量 linux环境为CentOS7.8 版本。 今天教大家怎么在CentOs环境中安装Java的开发环境。 在安装java之前我们先来了解一下YUM Yum(全称为 Yellow dog Updat…

【JavaEE初阶】简单了解wait和notify方法~

目录 🌟1、wait() 🌟2、notify() 🌟1、wait() (1)wait()方法与notify()方法都是Object类中的方法。 (2)wait()是让线程等待一段时间,死等——>状态WAITING:没有时间限制的等待.…

C++ | 语句的基础知识(夯实基础)

本文概要 本篇文章主要介绍数据结构中C的语句内容,适合有零基础的同学,文中描述和代码示例很详细,干货满满,感兴趣的小伙伴快来一起学习吧! 🌟🌟🌟个人简介🌟&#x1f…

CentOS 7.x 安装 ZooKeeper 并实现集群搭建

0. 集群结构 服务器IPhostname节点说明192.168.31.101master主节点192.168.31.102slave1从节点192.168.31.103 slave2 从节点 下面的安装与配置操作需要在三台服务器上都执行一遍。 1. 安装JDK ZooKeeper要求运行在 JDK 环境上,JDK安装教程可参考 CentOS 7.x 安装…

从点赞到数字货币:揭秘Diem币与Facebook的联系

大家都知道Facebook是一个全球知名的社交媒体平台,但你是否听说过与Facebook有关的数字货币Diem币呢?或许你会想,从点赞到数字货币,这是怎么回事?别着急,让我们一起揭秘Diem币与Facebook的联系。 首先&…

IP一键呼叫语音对讲怎么样?

IP一键呼叫语音对讲怎么样? IP一键呼叫语音对讲,让您的生活更加便利和安全! 无需复杂设置,轻松实现远程通话,随时随地与家人朋友沟通交流。APP端可实时监控家庭动态,保证家庭安全。 一键呼叫语音功能&am…

微信小程序——自定义组件

自定义组件 一、组件的创建二、组件的引用1、全局引用2、局部引用 三、全局引用和局部引用 一、组件的创建 第一步:在项目的根目录下创建文件夹components。 第二步:在components文件夹下创建文件夹card。 第三步:选中文件夹card 右键 选中…

openwrt广告屏蔽大师修复补丁luci-app-adbyby plus + lite

openwrt广告屏蔽大师修复补丁 目前使用方式然而有规则无法下载的通病所以可以手工拷贝随便哪里来的规则最后提示 补丁位置 : 地址 http://pan.ezdial.cn/nasone/a 备用:https://bak.ezdial.cn:8000/bakone/a 因什么值得买,在反复审核本文&…

如何在 AlmaLinux 8 上安装和使用 Docker

Docker 是面向开发人员和系统管理员的强大平台,可简化在软件容器内部署应用程序的过程。 容器允许您将应用程序及其所有部分(代码、运行时、系统工具、系统库——通常位于 /usr/bin 或 /usr/lib 中的任何内容)打包,以便它可以在任何 Linux 机器上一致地运…

Linux性能参数调优

内核的shmall和shmmax参数 SHMMAX配置了最大的内存segment的大小:这个设置的比SGA_MAX_SIZE大比较好。 SHMMIN最小的内存segment的大小 SHMMNI整个系统的内存segment的总个数 SHMSEG每个进程可以使用的内存segment的最大个数 配置信号灯( semphore …

微软 New Bing, Chat AI 绘图火力全开

嗯,今天的主角是, Microsoft New Bing! 在 Edge 里面,访问 www.bing.com,登录 Microsoft 账户,点击 CHAT, 就可以体验 Bing Chatbot. 这次, New Bing 无需加入 waitlist, 即可全面体验 ChatGPT DALL-E 的绘图功能 关键…

1、防刷限流实现1

1、本章诉求 限流的需求出现在许多常见的场景中: 秒杀活动,有人使用软件恶意刷单抢货,需要限流防止机器参与活动某api被各式各样系统广泛调用,严重消耗网络、内存等资源,需要合理限流 2、流程设计 3、方案实现 3.1…

【致敬未来的攻城狮计划】— 连续打卡第二十二天:RA2E1的RTC时钟日历

系列文章目录 1.连续打卡第一天:提前对CPK_RA2E1是瑞萨RA系列开发板的初体验,了解一下 2.开发环境的选择和调试(从零开始,加油) 3.欲速则不达,今天是对RA2E1 基础知识的补充学习。 4.e2 studio 使用教程 5.…

XXL-JOB中间件【实现分布式任务调度】

目录 1:XXL-JOB介绍 2:搭建XXL-JOB 2.1:调度中心 2.2:执行器 2.3:执行任务 3:分片广播 1:XXL-JOB介绍 XXL-JOB是一个轻量级分布式任务调度平台,其核心设计目标是开发迅速、学…