当前位置:网站首页>Still using simpledateformat for time formatting? Be careful of project collapse
Still using simpledateformat for time formatting? Be careful of project collapse
2022-06-24 23:24:00 【Sharp surge】
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();
}
}
}
Report errors :

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 produce Thread safety problem 了 !
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
from : It's still in use SimpleDateFormat Format the time ? Be careful of project collapse !
边栏推荐
猜你喜欢

RT-thread使用rt-kprintf

Getting started with the go Cobra command line tool
Mycms we media CMS V3.0, resource push optimization, new free template

Actipro WPF Controls 2022.1.2
Paddledtx v1.0 has been released, and its security and flexibility have been comprehensively improved!

慕思股份深交所上市:靠床垫和“洋老头”走红 市值224亿

Docker installation MySQL simple without pit

Some updates about a hand slider (6-18, JS reverse)

Epics record reference 2 -- epics process database concept
![[JS] - [array, Stack, queue, Link List basis] - Notes](/img/c6/a1bd3b8ef6476d7d549abcb442949a.png)
[JS] - [array, Stack, queue, Link List basis] - Notes
随机推荐
Uip1.0 active sending problem understanding
斐波那契
Financial management [2]
laravel学习笔记
Financial management [6]
[JS] - [array, stack, queue, linked list basics] - Notes
监听 Markdown 文件并热更新 Next.js 页面
376. Tâches mécaniques
【js】-【数组应用】-学习笔记
Paddledtx v1.0 has been released, and its security and flexibility have been comprehensively improved!
OpenSSL SSL_ read: Connection was reset, errno 10054
[basic knowledge] ~ half adder & full adder
SQL -convert function
257. detention of offenders
Construction equipment [5]
Chapter VI skills related to e-learning 5 (super parameter verification)
Bubble sort
Mousse shares listed on Shenzhen Stock Exchange: becoming popular by mattress and "foreign old man", with a market value of 22.4 billion yuan
R语言使用MatchIt包进行倾向性匹配分析、使用match.data函数构建匹配后的样本集合、通过双样本t检验分析(双独立样本t检验)来判断倾向性评分匹配后样本中的所有协变量的平衡情况
Binary lookup array subscript