当前位置:网站首页>Still using simpledateformat for time formatting? Be careful that the project collapses!
Still using simpledateformat for time formatting? Be careful that the project collapses!
2022-06-28 11:45:00 【Luohanxiang】
SimpleDateFormat.parse()The thread safety problem of methodThe wrong sample
Cause analysis of non thread safety
resolvent
SimpleDateFormat.format()The thread safety problem of methodThe wrong sample
Cause analysis of non thread safety
resolvent
SimpleDateFormat There are thread safety problems in multithreading environment .
1 SimpleDateFormat.parse() The thread safety problem of method
1.1 The wrong sample
Misuse SimpleDateFormat.parse() The code for is as follows :
import java.text.SimpleDateFormat;
public class SimpleDateFormatTest {
private static final SimpleDateFormat SIMPLE_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public static void main(String[] args) {
/**
* SimpleDateFormat Thread unsafe , Thread safety is not guaranteed ( No locks ) Under the circumstances , Global... Is prohibited SimpleDateFormat, Otherwise, the report will be wrong NumberFormatException
*
* private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
*/
for (int i = 0; i < 20; ++i) {
Thread thread = new Thread(() -> {
try {
// Incorrect writing can lead to thread safety problems
System.out.println(Thread.currentThread().getName() + "--" + SIMPLE_DATE_FORMAT.parse("2020-06-01 11:35:00"));
} catch (Exception e) {
e.printStackTrace();
}
}, "Thread-" + i);
thread.start();
}
}
}
1.2 Cause analysis of non thread safety
You can see in the source code :SimpleDateFormat Inherit DateFormat class ,SimpleDateFormat The conversion date is inherited from DateFormat Class Calendar Object to operate on ,Calendar Object will be used to date - Time calculation , Both used for format Methods are also used for parse Method .

SimpleDateFormat Of parse(String source) Method Will call... Inherited from the parent class DateFormat Of parse(String source) Method

DateFormat Of parse(String source) Method will call SimpleDateFormat Rewritten in parse(String text, ParsePosition pos) Method , There is one area of concern in this approach

SimpleDateFormat Rewritten in parse(String text, ParsePosition pos) Method is called establish(calendar) This method :

The method is called Calendar Of clear() Method

You can find that the whole process Calendar Object, which is not thread safe , If ,a Thread will calendar It's empty ,calendar There is no new value , Just at the right time b The thread just entered parse The method uses calendar object , That will cause thread safety problems !
Under normal circumstances :

Non thread safe processes :

1.3 resolvent
Method 1: Every thread new One SimpleDateFormat
import java.text.SimpleDateFormat;
public class SimpleDateFormatTest {
public static void main(String[] args) {
for (int i = 0; i < 20; ++i) {
Thread thread = new Thread(() -> {
try {
// Every thread new One
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(Thread.currentThread().getName() + "--" + simpleDateFormat.parse("2020-06-01 11:35:00"));
} catch (Exception e) {
e.printStackTrace();
}
}, "Thread-" + i);
thread.start();
}
}
}
The way 2:synchronized And so on
public class SimpleDateFormatTest {
private static final SimpleDateFormat SIMPLE_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public static void main(String[] args) {
for (int i = 0; i < 20; ++i) {
Thread thread = new Thread(() -> {
try {
synchronized (SIMPLE_DATE_FORMAT) {
System.out.println(Thread.currentThread().getName() + "--" + SIMPLE_DATE_FORMAT.parse("2020-06-01 11:35:00"));
}
} catch (Exception e) {
e.printStackTrace();
}
}, "Thread-" + i);
thread.start();
}
}
}
The way 3: Use ThreadLocal Create an independent variable for each thread
import java.text.DateFormat;
import java.text.SimpleDateFormat;
public class SimpleDateFormatTest {
private static final ThreadLocal<DateFormat> SAFE_SIMPLE_DATE_FORMAT = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
public static void main(String[] args) {
for (int i = 0; i < 20; ++i) {
Thread thread = new Thread(() -> {
try {
System.out.println(Thread.currentThread().getName() + "--" + SAFE_SIMPLE_DATE_FORMAT.get().parse("2020-06-01 11:35:00"));
} catch (Exception e) {
e.printStackTrace();
}
}, "Thread-" + i);
thread.start();
}
}
}
ThreadLocal See for details of the use of :
https://blog.csdn.net/QiuHaoqian/article/details/117077792
2 SimpleDateFormat.format() The thread safety problem of method
2.1 The wrong sample
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class SimpleDateFormatTest {
// Time formatting objects
private static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("mm:ss");
public static void main(String[] args) throws InterruptedException {
// Create a thread pool to perform tasks
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(
10, 10, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<>(1000));
for (int i = 0; i < 1000; i++) {
int finalI = i;
// Perform tasks
threadPool.execute(new Runnable() {
@Override
public void run() {
Date date = new Date(finalI * 1000); // Get the time object
formatAndPrint(date); // Perform time formatting
}
});
}
threadPool.shutdown(); // The thread pool closes after the task is executed
}
/**
* Format and print the time
*/
private static void formatAndPrint(Date date) {
String result = simpleDateFormat.format(date); // Perform formatting
System.out.println(" Time :" + result); // Print final results
}
}

As can be seen from the above results , The print result of the program has duplicate content , The correct situation is that there is no time for repetition .
2.2 Cause analysis of non thread safety
In order to find the problem , see SimpleDateFormat in format Method source code to check the problem ,format Source code is as follows :

From the above source code can be seen , In execution SimpleDateFormat.format() When the method is used , Will use calendar.setTime() Method to convert the input time , So let's think about this scenario :
Threads 1 Yes
calendar.setTime(date)Method , The time entered by the user is converted into the time required for later formatting ;Threads 1 Suspend execution , Threads 2 obtain CPU The time slice starts to execute ;
Threads 2 Yes
calendar.setTime(date)Method , The time has been modified ;Threads 2 Suspend execution , Threads 1 obtain CPU Time slice continues , Because the thread 1 And thread 2 Using the same object , And time has been threaded 2 Revised , So when the thread 1 There will be thread safety problems when the execution continues .
Under normal circumstances , This is how the program works :

The non thread safe execution process is like this :

2.3 resolvent
There are also three solutions
Method 1: Every thread new One SimpleDateFormat
public class SimpleDateFormatTest {
public static void main(String[] args) throws InterruptedException {
// Create a thread pool to perform tasks
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(
10, 10, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<>(1000));
for (int i = 0; i < 1000; i++) {
int finalI = i;
// Perform tasks
threadPool.execute(new Runnable() {
@Override
public void run() {
// Get the time object
Date date = new Date(finalI * 1000);
// Perform time formatting
formatAndPrint(date);
}
});
}
// The thread pool closes after the task is executed
threadPool.shutdown();
}
/**
* Format and print the time
*/
private static void formatAndPrint(Date date) {
String result = new SimpleDateFormat("mm:ss").format(date); // Perform formatting
System.out.println(" Time :" + result); // Print final results
}
}
The way 2:synchronized And so on
All threads have to queue up to perform some business , In this way, the efficiency of the program will be reduced
public class SimpleDateFormatTest {
// Time formatting objects
private static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("mm:ss");
public static void main(String[] args) throws InterruptedException {
// Create a thread pool to perform tasks
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(
10, 10, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<>(1000));
for (int i = 0; i < 1000; i++) {
int finalI = i;
// Perform tasks
threadPool.execute(new Runnable() {
@Override
public void run() {
Date date = new Date(finalI * 1000); // Get the time object
formatAndPrint(date); // Perform time formatting
}
});
}
// The thread pool closes after the task is executed
threadPool.shutdown();
}
/**
* Format and print the time
*/
private static void formatAndPrint(Date date) {
// Perform formatting
String result = null;
// Lock
synchronized (SimpleDateFormatTest.class) {
result = simpleDateFormat.format(date);
}
// Print final results
System.out.println(" Time :" + result);
}
}
The way 3: Use ThreadLocal Create an independent variable for each thread
public class SimpleDateFormatTest {
// establish ThreadLocal And set the default value
private static ThreadLocal<SimpleDateFormat> dateFormatThreadLocal =
ThreadLocal.withInitial(() -> new SimpleDateFormat("mm:ss"));
public static void main(String[] args) {
// Create a thread pool to perform tasks
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(10, 10, 60,
TimeUnit.SECONDS, new LinkedBlockingQueue<>(1000));
// Perform tasks
for (int i = 0; i < 1000; i++) {
int finalI = i;
// Perform tasks
threadPool.execute(() -> {
Date date = new Date(finalI * 1000); // Get the time object
formatAndPrint(date); // Perform time formatting
});
}
threadPool.shutdown(); // The thread pool closes after the task is executed
}
/**
* Format and print the time
*/
private static void formatAndPrint(Date date) {
String result = dateFormatThreadLocal.get().format(date); // Perform formatting
System.out.println(" Time :" + result); // Print final results
}
}
source :blog.csdn.net/QiuHaoqian/article/
details/116594422
边栏推荐
猜你喜欢

js中的class类模式及语法 2021.11.10

Practice and Thinking on the architecture of a set of 100000 TPS im integrated message system

QML控件类型:TabBar

For example, the visual appeal of the live broadcast of NBA Finals can be seen like this?

Day39 prototype chain and page fireworks effect 2021.10.13

Thesis reading (59):keyword based diverse image retrieval with variable multiple instance graph

Training notice | special training notice on epidemic prevention and security prevention for overseas Chinese funded enterprises, institutions and personnel in 2022

行业分析| 快对讲,楼宇对讲

day36 js笔记 ECMA6语法 2021.10.09

The default point of this in JS and how to modify it to 2021.11.09
随机推荐
This Exception was thrown from a job compiled with Burst, which has limited exception support. report errors
Download and install mysql5.7 for windows 10
人人都可以参与开源!龙蜥社区最不容错过的开发者活动来了
什么是主链系统?
Calculate time using calendar
It is safer for individuals to choose which securities company to open an account for buying floor funds
Redis6 1: what problems can be solved by the introduction of NoSQL and redis?
FTP protocol for Wireshark packet capture analysis
Day34 JS notes regular expression 2021.09.29
【无标题】虚拟机vmnet0找不到且报错:没有未桥接的主机网络适配器
Day33 JS note event (Part 2) September 28, 2021
Day31 JS notes DOM 2021.09.26
day37 js笔记 运动函数 2021.10.11
Zero foundation self-study SQL course | if function
100 important knowledge points that SQL must master: retrieving data
Which programming language will attract excellent talents?
Intranet penetration in the working group environment: some basic methods
Packaging and publishing application of jetpack compose desktop version
一套十万级TPS的IM综合消息系统的架构实践与思考
Training notice | special training notice on epidemic prevention and security prevention for overseas Chinese funded enterprises, institutions and personnel in 2022