当前位置:网站首页>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
边栏推荐
- kubernetes之ReplicationController与ReplicaSet
- Differences between the use of structs and classes
- kubernetes之探针
- 京东三面:我要查询千万级数据量的表,怎么操作?
- Tao and art of R & D Efficiency - Tao chapter
- Re8: reading papers Hier spcnet: a legal stat hierarchy based heterogeneous network for computing legal case
- srec_cat 常用参数的使用
- 中金证券vip账户找谁开安全啊?
- Vlang's way of beating drums
- 【开发教程9】疯壳·ARM功能手机-I2C教程
猜你喜欢

Re7:读论文 FLA/MLAC Learning to Predict Charges for Criminal Cases with Legal Basis

带你一分钟了解对称加密和非对称加密

该怎么写单元测试呢

Docker install redis? How to configure persistence policy?

guetzli简单使用

NUC 11构建 ESXi 7.0.3f安装网卡驱动-V2(2022年7月升级版)
Final consistency distributed transaction TCC

PXE高效批量网络装机

The difference and efficiency comparison of three methods of C # conversion integer

40个高质量信息管理专业毕设项目分享【源码+论文】(六)
随机推荐
Vlang's way of beating drums
【开发教程7】疯壳·开源蓝牙心率防水运动手环-电容触摸
视频媒介video
Trends in software testing tools in 2021
Win11怎么自动清理回收站?
Pyqt5 rapid development and practice 3.4 signal and slot correlation
6种方法帮你搞定SimpleDateFormat类不是线程安全的问题
VS2017打开项目提示需要迁移的解决方法
2022牛客暑期多校训练营2(BDGHJKL)
Linux Installation mysql8.0.29 detailed tutorial
[arm learning (9) ARM compiler understanding learning (armcc/armclang)]
匿名方法和lambda表达式使用的区别
京东三面:我要查询千万级数据量的表,怎么操作?
别用Xshell了,试试这个更现代的终端连接工具
2022软件测试技能 Postman+newman+jenkins 持续集成 实战教程
【飞控开发基础教程2】疯壳·开源编队无人机-定时器(LED 航情灯、指示灯闪烁)
Win11怎么重新安装系统?
PyQt5快速开发与实战 3.4 信号与槽关联
综合设计一个OPPE主页--布局与初始化
带你一分钟了解对称加密和非对称加密