当前位置:网站首页>Simpledateformat has thread safety problems in multi-threaded environments.
Simpledateformat has thread safety problems in multi-threaded environments.
2022-06-23 18:14:00 【Zhangshao】
List of articles
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();
}
}
}
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 :
1、 Threads 1 Yes calendar.setTime(date) Method , The time entered by the user is converted into the time required for later formatting ;
2、 Threads 1 Suspend execution , Threads 2 obtain CPU The time slice starts to execute ;
3、 Threads 2 Yes calendar.setTime(date) Method , The time has been modified ;
4、 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
}
}
边栏推荐
- Alien world, real presentation, how does the alien version of Pokemon go achieve?
- 12. Manage network environment
- How to create a three elimination game
- Kotlin practical skills you should know
- PostgreSQL series articles -- the world's most advanced open source relational database
- 信用卡产品开发周期从23周缩短至9周,银行运维组织如何转向敏捷?
- Paper reading (58):research and implementation of global path planning for unmanned surface vehicle based
- 【ESP8266-01s】獲取天氣,城市,北京時間
- Method of copying web page content and automatically adding copyright information (compatible with ie, Firefox and chrome)
- 论文阅读 (47):DTFD-MIL: Double-Tier Feature Distillation Multiple Instance Learning for Histopathology..
猜你喜欢

论文阅读 (50):A Novel Matrix Game with Payoffs of Maxitive Belief Structure

【Unity】插件TextAnimator 新手使用说明

Redis 集群

The battlefield of live broadcast e-commerce is not in the live broadcast room

如何利用好每天的时间高效复习?

Wiley- Open Science Joint Symposium of the documentation and information center of the Chinese Academy of Sciences, lecture 2: open access journal selection and paper submission

csdn涨薪秘籍之Jenkins集成allure测试报告全套教程

SimpleDateFormat在多线程环境下存在线程安全问题。

客服系统搭建教程_宝塔面板下安装使用方式_可对接公众号_支持APP/h5多租户运营...

QML类型:Loader
随机推荐
[esp8266-01s] get weather, city, Beijing time
Easygbs playback screen is continuously loading. Troubleshooting
[failure announcement] there is a problem with the redis that replaces memcached, causing the website to fail
客服系统搭建教程_宝塔面板下安装使用方式_可对接公众号_支持APP/h5多租户运营...
How to solve the problem that the esp8266-01s cannot connect to Huawei routers
Latex编译成功但是无法输出到PDF
论文阅读 (53):Universal Adversarial Perturbations
异步or线程池
深入理解 padding
《致敬百年巨匠 , 数藏袖珍书票》
【ESP8266-01s】獲取天氣,城市,北京時間
Establishment and use of SSL VPN (OpenVPN)
Wechat applet reports an error [app.json file content error] app json: app. JSON not found
README
Rancher2.6全新Monitoring快速入门
Goframe framework: add tracing Middleware
Redis Cluster
对抗攻击与防御 (2):对抗样本的反制策略
How to create a three elimination game
Revil - blackmail Virus Emergency Response