当前位置:网站首页>There are six ways to help you deal with the simpledateformat class, which is not a thread safety problem
There are six ways to help you deal with the simpledateformat class, which is not a thread safety problem
2022-07-26 16:49:00 【InfoQ】
repeat SimpleDateFormat Thread safety of class
package io.binghe.concurrent.lab06;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
/**
* @author binghe
* @version 1.0.0
* @description test SimpleDateFormat Thread security problem
*/
public class SimpleDateFormatTest01 {
// The total number of execution
private static final int EXECUTE_COUNT = 1000;
// Number of threads running at the same time
private static final int THREAD_COUNT = 20;
//SimpleDateFormat object
private static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
public static void main(String[] args) throws InterruptedException {
final Semaphore semaphore = new Semaphore(THREAD_COUNT);
final CountDownLatch countDownLatch = new CountDownLatch(EXECUTE_COUNT);
ExecutorService executorService = Executors.newCachedThreadPool();
for (int i = 0; i < EXECUTE_COUNT; i++){
executorService.execute(() -> {
try {
semaphore.acquire();
try {
simpleDateFormat.parse("2020-01-01");
} catch (ParseException e) {
System.out.println(" Threads :" + Thread.currentThread().getName() + " Failed to format date ");
e.printStackTrace();
System.exit(1);
}catch (NumberFormatException e){
System.out.println(" Threads :" + Thread.currentThread().getName() + " Failed to format date ");
e.printStackTrace();
System.exit(1);
}
semaphore.release();
} catch (InterruptedException e) {
System.out.println(" Semaphore error ");
e.printStackTrace();
System.exit(1);
}
countDownLatch.countDown();
});
}
countDownLatch.await();
executorService.shutdown();
System.out.println(" All threads successfully formatted date ");
}
}simpleDateFormat.parse("2020-01-01");Exception in thread "pool-1-thread-4" Exception in thread "pool-1-thread-1" Exception in thread "pool-1-thread-2" Threads :pool-1-thread-7 Failed to format date
Threads :pool-1-thread-9 Failed to format date
Threads :pool-1-thread-10 Failed to format date
Exception in thread "pool-1-thread-3" Exception in thread "pool-1-thread-5" Exception in thread "pool-1-thread-6" Threads :pool-1-thread-15 Failed to format date
Threads :pool-1-thread-21 Failed to format date
Exception in thread "pool-1-thread-23" Threads :pool-1-thread-16 Failed to format date
Threads :pool-1-thread-11 Failed to format date
java.lang.ArrayIndexOutOfBoundsException
Threads :pool-1-thread-27 Failed to format date
at java.lang.System.arraycopy(Native Method)
at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:597)
at java.lang.StringBuffer.append(StringBuffer.java:367)
at java.text.DigitList.getLong(DigitList.java:191) Threads :pool-1-thread-25 Failed to format date
at java.text.DecimalFormat.parse(DecimalFormat.java:2084)
at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:1869)
at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1514)
Threads :pool-1-thread-14 Failed to format date
at java.text.DateFormat.parse(DateFormat.java:364)
at io.binghe.concurrent.lab06.SimpleDateFormatTest01.lambda$main$0(SimpleDateFormatTest01.java:47)
Threads :pool-1-thread-13 Failed to format date at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
java.lang.NumberFormatException: For input string: ""
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
Threads :pool-1-thread-20 Failed to format date at java.lang.Long.parseLong(Long.java:601)
at java.lang.Long.parseLong(Long.java:631)
at java.text.DigitList.getLong(DigitList.java:195)
at java.text.DecimalFormat.parse(DecimalFormat.java:2084)
at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:2162)
at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1514)
at java.text.DateFormat.parse(DateFormat.java:364)
at io.binghe.concurrent.lab06.SimpleDateFormatTest01.lambda$main$0(SimpleDateFormatTest01.java:47)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
java.lang.NumberFormatException: For input string: ""
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Long.parseLong(Long.java:601)
at java.lang.Long.parseLong(Long.java:631)
at java.text.DigitList.getLong(DigitList.java:195)
at java.text.DecimalFormat.parse(DecimalFormat.java:2084)
at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:1869)
at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1514)
at java.text.DateFormat.parse(DateFormat.java:364)
Process finished with exit code 1SimpleDateFormat Why classes are not thread safe ?
/**
* The {@link Calendar} instance used for calculating the date-time fields
* and the instant of time. This field is used for both formatting and
* parsing.
*
* <p>Subclasses should initialize this field to a {@link Calendar}
* appropriate for the {@link Locale} associated with this
* <code>DateFormat</code>.
* @serial
*/
protected Calendar calendar; Copy @Override
public Date parse(String text, ParsePosition pos){
################ Omit here N Line code ##################
Date parsedDate;
try {
parsedDate = calb.establish(calendar).getTime();
// If the year value is ambiguous,
// then the two-digit year == the default start year
if (ambiguousYear[0]) {
if (parsedDate.before(defaultCenturyStart)) {
parsedDate = calb.addYear(100).establish(calendar).getTime();
}
}
}
// An IllegalArgumentException will be thrown by Calendar.getTime()
// if any fields are out of range, e.g., MONTH == 17.
catch (IllegalArgumentException e) {
pos.errorIndex = start;
pos.index = oldStart;
return null;
}
return parsedDate;
}Calendar establish(Calendar cal) {
boolean weekDate = isSet(WEEK_YEAR)
&& field[WEEK_YEAR] > field[YEAR];
if (weekDate && !cal.isWeekDateSupported()) {
// Use YEAR instead
if (!isSet(YEAR)) {
set(YEAR, field[MAX_FIELD + WEEK_YEAR]);
}
weekDate = false;
}
cal.clear();
// Set the fields from the min stamp to the max stamp so that
// the field resolution works in the Calendar.
for (int stamp = MINIMUM_USER_STAMP; stamp < nextStamp; stamp++) {
for (int index = 0; index <= maxFieldIndex; index++) {
if (field[index] == stamp) {
cal.set(index, field[MAX_FIELD + index]);
break;
}
}
}
if (weekDate) {
int weekOfYear = isSet(WEEK_OF_YEAR) ? field[MAX_FIELD + WEEK_OF_YEAR] : 1;
int dayOfWeek = isSet(DAY_OF_WEEK) ?
field[MAX_FIELD + DAY_OF_WEEK] : cal.getFirstDayOfWeek();
if (!isValidDayOfWeek(dayOfWeek) && cal.isLenient()) {
if (dayOfWeek >= 8) {
dayOfWeek--;
weekOfYear += dayOfWeek / 7;
dayOfWeek = (dayOfWeek % 7) + 1;
} else {
while (dayOfWeek <= 0) {
dayOfWeek += 7;
weekOfYear--;
}
}
dayOfWeek = toCalendarDayOfWeek(dayOfWeek);
}
cal.setWeekDate(field[MAX_FIELD + WEEK_YEAR], weekOfYear, dayOfWeek);
}
return cal;
}solve SimpleDateFormat Thread safety of class
1. Local variable method
package io.binghe.concurrent.lab06;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
/**
* @author binghe
* @version 1.0.0
* @description Local variable method to solve SimpleDateFormat Thread safety of class
*/
public class SimpleDateFormatTest02 {
// The total number of execution
private static final int EXECUTE_COUNT = 1000;
// Number of threads running at the same time
private static final int THREAD_COUNT = 20;
public static void main(String[] args) throws InterruptedException {
final Semaphore semaphore = new Semaphore(THREAD_COUNT);
final CountDownLatch countDownLatch = new CountDownLatch(EXECUTE_COUNT);
ExecutorService executorService = Executors.newCachedThreadPool();
for (int i = 0; i < EXECUTE_COUNT; i++){
executorService.execute(() -> {
try {
semaphore.acquire();
try {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
simpleDateFormat.parse("2020-01-01");
} catch (ParseException e) {
System.out.println(" Threads :" + Thread.currentThread().getName() + " Failed to format date ");
e.printStackTrace();
System.exit(1);
}catch (NumberFormatException e){
System.out.println(" Threads :" + Thread.currentThread().getName() + " Failed to format date ");
e.printStackTrace();
System.exit(1);
}
semaphore.release();
} catch (InterruptedException e) {
System.out.println(" Semaphore error ");
e.printStackTrace();
System.exit(1);
}
countDownLatch.countDown();
});
}
countDownLatch.await();
executorService.shutdown();
System.out.println(" All threads successfully formatted date ");
}
} All threads successfully formatted date 2. Synchronous lock mode
package io.binghe.concurrent.lab06;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
/**
* @author binghe
* @version 1.0.0
* @description adopt Synchronized Lock resolution SimpleDateFormat Thread safety of class
*/
public class SimpleDateFormatTest03 {
// The total number of execution
private static final int EXECUTE_COUNT = 1000;
// Number of threads running at the same time
private static final int THREAD_COUNT = 20;
//SimpleDateFormat object
private static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
public static void main(String[] args) throws InterruptedException {
final Semaphore semaphore = new Semaphore(THREAD_COUNT);
final CountDownLatch countDownLatch = new CountDownLatch(EXECUTE_COUNT);
ExecutorService executorService = Executors.newCachedThreadPool();
for (int i = 0; i < EXECUTE_COUNT; i++){
executorService.execute(() -> {
try {
semaphore.acquire();
try {
synchronized (simpleDateFormat){
simpleDateFormat.parse("2020-01-01");
}
} catch (ParseException e) {
System.out.println(" Threads :" + Thread.currentThread().getName() + " Failed to format date ");
e.printStackTrace();
System.exit(1);
}catch (NumberFormatException e){
System.out.println(" Threads :" + Thread.currentThread().getName() + " Failed to format date ");
e.printStackTrace();
System.exit(1);
}
semaphore.release();
} catch (InterruptedException e) {
System.out.println(" Semaphore error ");
e.printStackTrace();
System.exit(1);
}
countDownLatch.countDown();
});
}
countDownLatch.await();
executorService.shutdown();
System.out.println(" All threads successfully formatted date ");
}
}synchronized (simpleDateFormat){
simpleDateFormat.parse("2020-01-01");
} All threads successfully formatted date 3. Lock mode
package io.binghe.concurrent.lab06;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* @author binghe
* @version 1.0.0
* @description adopt Lock Lock resolution SimpleDateFormat Thread safety of class
*/
public class SimpleDateFormatTest04 {
// The total number of execution
private static final int EXECUTE_COUNT = 1000;
// Number of threads running at the same time
private static final int THREAD_COUNT = 20;
//SimpleDateFormat object
private static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
//Lock object
private static Lock lock = new ReentrantLock();
public static void main(String[] args) throws InterruptedException {
final Semaphore semaphore = new Semaphore(THREAD_COUNT);
final CountDownLatch countDownLatch = new CountDownLatch(EXECUTE_COUNT);
ExecutorService executorService = Executors.newCachedThreadPool();
for (int i = 0; i < EXECUTE_COUNT; i++){
executorService.execute(() -> {
try {
semaphore.acquire();
try {
lock.lock();
simpleDateFormat.parse("2020-01-01");
} catch (ParseException e) {
System.out.println(" Threads :" + Thread.currentThread().getName() + " Failed to format date ");
e.printStackTrace();
System.exit(1);
}catch (NumberFormatException e){
System.out.println(" Threads :" + Thread.currentThread().getName() + " Failed to format date ");
e.printStackTrace();
System.exit(1);
}finally {
lock.unlock();
}
semaphore.release();
} catch (InterruptedException e) {
System.out.println(" Semaphore error ");
e.printStackTrace();
System.exit(1);
}
countDownLatch.countDown();
});
}
countDownLatch.await();
executorService.shutdown();
System.out.println(" All threads successfully formatted date ");
}
}finally {
lock.unlock();
} Copy All threads successfully formatted date 4.ThreadLocal The way
package io.binghe.concurrent.lab06;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
/**
* @author binghe
* @version 1.0.0
* @description adopt ThreadLocal solve SimpleDateFormat Thread safety of class
*/
public class SimpleDateFormatTest05 {
// The total number of execution
private static final int EXECUTE_COUNT = 1000;
// Number of threads running at the same time
private static final int THREAD_COUNT = 20;
private static ThreadLocal<DateFormat> threadLocal = new ThreadLocal<DateFormat>(){
@Override
protected DateFormat initialValue() {
return new SimpleDateFormat("yyyy-MM-dd");
}
};
public static void main(String[] args) throws InterruptedException {
final Semaphore semaphore = new Semaphore(THREAD_COUNT);
final CountDownLatch countDownLatch = new CountDownLatch(EXECUTE_COUNT);
ExecutorService executorService = Executors.newCachedThreadPool();
for (int i = 0; i < EXECUTE_COUNT; i++){
executorService.execute(() -> {
try {
semaphore.acquire();
try {
threadLocal.get().parse("2020-01-01");
} catch (ParseException e) {
System.out.println(" Threads :" + Thread.currentThread().getName() + " Failed to format date ");
e.printStackTrace();
System.exit(1);
}catch (NumberFormatException e){
System.out.println(" Threads :" + Thread.currentThread().getName() + " Failed to format date ");
e.printStackTrace();
System.exit(1);
}
semaphore.release();
} catch (InterruptedException e) {
System.out.println(" Semaphore error ");
e.printStackTrace();
System.exit(1);
}
countDownLatch.countDown();
});
}
countDownLatch.await();
executorService.shutdown();
System.out.println(" All threads successfully formatted date ");
}
} All threads successfully formatted date package io.binghe.concurrent.lab06;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
/**
* @author binghe
* @version 1.0.0
* @description adopt ThreadLocal solve SimpleDateFormat Thread safety of class
*/
public class SimpleDateFormatTest06 {
// The total number of execution
private static final int EXECUTE_COUNT = 1000;
// Number of threads running at the same time
private static final int THREAD_COUNT = 20;
private static ThreadLocal<DateFormat> threadLocal = new ThreadLocal<DateFormat>();
private static DateFormat getDateFormat(){
DateFormat dateFormat = threadLocal.get();
if(dateFormat == null){
dateFormat = new SimpleDateFormat("yyyy-MM-dd");
threadLocal.set(dateFormat);
}
return dateFormat;
}
public static void main(String[] args) throws InterruptedException {
final Semaphore semaphore = new Semaphore(THREAD_COUNT);
final CountDownLatch countDownLatch = new CountDownLatch(EXECUTE_COUNT);
ExecutorService executorService = Executors.newCachedThreadPool();
for (int i = 0; i < EXECUTE_COUNT; i++){
executorService.execute(() -> {
try {
semaphore.acquire();
try {
getDateFormat().parse("2020-01-01");
} catch (ParseException e) {
System.out.println(" Threads :" + Thread.currentThread().getName() + " Failed to format date ");
e.printStackTrace();
System.exit(1);
}catch (NumberFormatException e){
System.out.println(" Threads :" + Thread.currentThread().getName() + " Failed to format date ");
e.printStackTrace();
System.exit(1);
}
semaphore.release();
} catch (InterruptedException e) {
System.out.println(" Semaphore error ");
e.printStackTrace();
System.exit(1);
}
countDownLatch.countDown();
});
}
countDownLatch.await();
executorService.shutdown();
System.out.println(" All threads successfully formatted date ");
}
}5.DateTimeFormatter The way
package io.binghe.concurrent.lab06;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
/**
* @author binghe
* @version 1.0.0
* @description adopt DateTimeFormatter Class to solve the problem of thread safety
*/
public class SimpleDateFormatTest07 {
// The total number of execution
private static final int EXECUTE_COUNT = 1000;
// Number of threads running at the same time
private static final int THREAD_COUNT = 20;
private static DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
public static void main(String[] args) throws InterruptedException {
final Semaphore semaphore = new Semaphore(THREAD_COUNT);
final CountDownLatch countDownLatch = new CountDownLatch(EXECUTE_COUNT);
ExecutorService executorService = Executors.newCachedThreadPool();
for (int i = 0; i < EXECUTE_COUNT; i++){
executorService.execute(() -> {
try {
semaphore.acquire();
try {
LocalDate.parse("2020-01-01", formatter);
}catch (Exception e){
System.out.println(" Threads :" + Thread.currentThread().getName() + " Failed to format date ");
e.printStackTrace();
System.exit(1);
}
semaphore.release();
} catch (InterruptedException e) {
System.out.println(" Semaphore error ");
e.printStackTrace();
System.exit(1);
}
countDownLatch.countDown();
});
}
countDownLatch.await();
executorService.shutdown();
System.out.println(" All threads successfully formatted date ");
}
} All threads successfully formatted date 6.joda-time The way
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.9.9</version>
</dependency>package io.binghe.concurrent.lab06;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
/**
* @author binghe
* @version 1.0.0
* @description adopt DateTimeFormatter Class to solve the problem of thread safety
*/
public class SimpleDateFormatTest08 {
// The total number of execution
private static final int EXECUTE_COUNT = 1000;
// Number of threads running at the same time
private static final int THREAD_COUNT = 20;
private static DateTimeFormatter dateTimeFormatter = DateTimeFormat.forPattern("yyyy-MM-dd");
public static void main(String[] args) throws InterruptedException {
final Semaphore semaphore = new Semaphore(THREAD_COUNT);
final CountDownLatch countDownLatch = new CountDownLatch(EXECUTE_COUNT);
ExecutorService executorService = Executors.newCachedThreadPool();
for (int i = 0; i < EXECUTE_COUNT; i++){
executorService.execute(() -> {
try {
semaphore.acquire();
try {
DateTime.parse("2020-01-01", dateTimeFormatter).toDate();
}catch (Exception e){
System.out.println(" Threads :" + Thread.currentThread().getName() + " Failed to format date ");
e.printStackTrace();
System.exit(1);
}
semaphore.release();
} catch (InterruptedException e) {
System.out.println(" Semaphore error ");
e.printStackTrace();
System.exit(1);
}
countDownLatch.countDown();
});
}
countDownLatch.await();
executorService.shutdown();
System.out.println(" All threads successfully formatted date ");
}
}import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter; All threads successfully formatted date solve SimpleDateFormat Class thread safety issues of the program summary
边栏推荐
- Re8: reading papers Hier spcnet: a legal stat hierarchy based heterogeneous network for computing legal case
- movable-view 组件(可上下左右拖动 )
- Guetzli simple to use
- TDengine 落地协鑫能科,数百亿数据压缩至 600GB
- Want the clouds in the picture to float? Video editing services can be achieved in three steps with one click
- Operating system migration practice: deploying MySQL database on openeuler
- Marketing guide | several common micro blog marketing methods
- NUC 11构建 ESXi 7.0.3f安装网卡驱动-V2(2022年7月升级版)
- Acl-ijcai-sigir top conference paper report meeting (AIS 2022) Note 3: dialogue and generation
- 最终一致性性分布式事务 TCC
猜你喜欢

40个高质量信息管理专业毕设项目分享【源码+论文】(六)

Oracle创建表分区后,查询的时候不给出partition,但是会给分区字段指定的值,会不会自动按照分区查询?

工作流引擎在vivo营销自动化中的应用实践

Win11怎么重新安装系统?

营销指南 | 几种常见的微博营销打法

Matlab论文插图绘制模板第40期—带偏移扇区的饼图

第一章概述-------第一节--1.3互联网的组成

What is the complexity often said during the interview?

How to write unit tests

Marxan模型保护区优化与保护空缺甄选技术、InVEST生态系统中的应用
随机推荐
guetzli简单使用
极大似然估计
DTS is equipped with a new self-developed kernel, which breaks through the key technology of the three center architecture of the two places Tencent cloud database
C # method to read the text content of all files in the local folder
docker安装redis?如何配置持久化策略?
Docker install redis? How to configure persistence policy?
微信小程序---网络数据请求
ES:Compressor detection can only be called on some xcontent bytes or compressed xcontent bytes
JD Sanmian: I want to query a table with tens of millions of data. How can I operate it?
如何保证缓存和数据库一致性
A preliminary understanding of MVC and ECS design architectures
2022-2023 信息管理毕业设计选题题目推荐
Alibaba Cloud Toolkit —— 项目一键部署工具
DTS搭载全新自研内核,突破两地三中心架构的关键技术|腾讯云数据库
结构体和类使用的区别
Digital currency of quantitative transactions - merge transaction by transaction data through timestamp and direction (large order consolidation)
公安部发出暑期旅游客运交通安全预警:手握方向盘 绷紧安全弦
最终一致性性分布式事务 TCC
Configmap of kubernetes
Operating system migration practice: deploying MySQL database on openeuler