Java 高级编程之避坑指南

* 1. 不要使用 SimpleDateFormat
<https://blog.csdn.net/kisslotus/article/details/90210607#1__SimpleDateFormat_1>
* 1.1 常见的错误使用方式
<https://blog.csdn.net/kisslotus/article/details/90210607#11__2>
* 1.2 解决方案 1
<https://blog.csdn.net/kisslotus/article/details/90210607#12__1_51>
* 1.3 解决方案 2
<https://blog.csdn.net/kisslotus/article/details/90210607#13__2_71>
* 2. 分布式唯一ID生成器UidGenerator
<https://blog.csdn.net/kisslotus/article/details/90210607#2_IDUidGenerator_119>


<>1. 不要使用 SimpleDateFormat

<>1.1 常见的错误使用方式

一般我们使用SimpleDateFormat的时候会把它定义为一个静态变量,避免频繁创建它的对象实例,如下代码:
单线程场景使用时没有问题,多线程场景下使用时会报错:java.lang.NumberFormatException: multiple points
单线程

* Date formats are not synchronized.
* It is recommended to create separate format instances for each thread.
* If multiple threads access a format concurrently, it must be synchronized
externally.
此外,SimpleDateFormat和它继承的DateFormat类也不是线程安全的。 public class SimpleDateFormatTest
{ private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd
HH:mm:ss"); public static String formatDate(Date date) throws ParseException {
return sdf.format(date); } public static Date parse(String strDate) throws
ParseException{ return sdf.parse(strDate); } public static void main(String[]
args) throws InterruptedException, ParseException { System.out.println(sdf.
format(new Date())); } public static void main(String[] args) throws
InterruptedException, ParseException { ExecutorService service = Executors.
newFixedThreadPool(100); for (int i = 0; i < 20; i++) { service.execute(() -> {
for (int j = 0; j < 10; j++) { try { System.out.println(parse("2018-01-02
09:45:59")); } catch (ParseException e) { e.printStackTrace(); } } }); } //
等待上述的线程执行完 service.shutdown(); service.awaitTermination(1, TimeUnit.DAYS); } }
低效的解决方案有:1)每次都生成一个新的对象,缺点是低效,创建大量的临时对象。2)使用 synchronized
关键字,缺点是:降低了并发性,大量并发时进程阻塞。下面两种是推荐的可选方式,更推荐方案 2.

<>1.2 解决方案 1

ThreadLocal可以确保每个线程都可以得到单独的一个SimpleDateFormat的对象。
private static ThreadLocal<DateFormat> threadLocal = new ThreadLocal<DateFormat
>() { @Override protected DateFormat initialValue() { return new
SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); } }; public static Date parse(String
dateStr) throws ParseException { return threadLocal.get().parse(dateStr); }
public static String format(Date date) { return threadLocal.get().format(date);
}
<>1.3 解决方案 2

DateTimeFormatter:

* This class is immutable and thread-safe. import java.text.ParseException;
import java.time.LocalDateTime; import java.time.format.DateTimeFormatter;
import java.util.concurrent.ExecutorService; import java.util.concurrent.
Executors; import java.util.concurrent.TimeUnit; public class
SimpleDateFormatTest { private static final DateTimeFormatter formatter =
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); public static String
formatDate2(LocalDateTime date) { return formatter.format(date); } public static
LocalDateTimeparse2(String dateNow) { return LocalDateTime.parse(dateNow,
formatter); } public static void main(String[] args) throws InterruptedException
, ParseException { ExecutorService service = Executors.newFixedThreadPool(100);
// 20个线程 for (int i = 0; i < 20; i++) { service.execute(() -> { for (int j = 0;
j< 10; j++) { try { System.out.println(parse2(formatDate2(LocalDateTime.now())))
; } catch (Exception e) { e.printStackTrace(); } } }); } // 等待上述的线程执行完 service.
shutdown(); service.awaitTermination(1, TimeUnit.DAYS); } }
<>2. 分布式唯一ID生成器UidGenerator

百度开源的分布式唯一ID生成器UidGenerator,解决了时钟回拨问题
<https://mp.weixin.qq.com/s?__biz=MzIwMzY1OTU1NQ==&mid=2247486160&idx=1&sn=5f04a9f3c8a9776ff432207207041aca&chksm=96cd4a9ca1bac38ac64baa17d5078259934a73e7315231da7e6a1d0965959076c532910857be>

友情链接
KaDraw流程图
API参考文档
OK工具箱
云服务器优惠
阿里云优惠券
腾讯云优惠券
华为云优惠券
站点信息
问题反馈
邮箱:[email protected]
QQ群:637538335
关注微信