简单网站开发项目实例企业网址是怎么写的
news/
2025/10/3 22:00:56/
文章来源:
简单网站开发项目实例,企业网址是怎么写的,制作网站教程,wordpress建单页面论坛提起SimpleDateFormat类#xff0c;想必做过Java开发的童鞋都不会感到陌生。没错#xff0c;它就是Java中提供的日期时间的转化类。这里#xff0c; 为什么说SimpleDateFormat类有线程安全问题呢#xff1f;有些小伙伴可能会提出疑问#xff1a;我们生产环境上一直在使用S…提起SimpleDateFormat类想必做过Java开发的童鞋都不会感到陌生。没错它就是Java中提供的日期时间的转化类。这里 为什么说SimpleDateFormat类有线程安全问题呢有些小伙伴可能会提出疑问我们生产环境上一直在使用SimpleDateFormat 类来解析和格式化日期和时间类型的数据一直都没有问题啊我的回答是没错那是因为你们的系统达不到 SimpleDateFormat类出现问题的并发量也就是说你们的系统没啥负载 接下来我们就一起看下在高并发下SimpleDateFormat类为何会出现安全问题以及如何解决SimpleDateFormat类的安全问 题。
重现SimpleDateFormat线程安全问题
public class SimpleDateFormatTest01 {//执行总次数private static final int EXECUTE_COUNT 1000;//同时运行的线程数量private static final int THREAD_COUNT 20;//SimpleDateFormat对象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(线程 Thread.currentThread().getName() 格式化日期失败);e.printStackTrace();System.exit(1);} catch (NumberFormatException e) {System.out.println(线程 Thread.currentThread().getName() 格式化日期失败);e.printStackTrace();System.exit(1);}semaphore.release();} catch (InterruptedException e) {System.out.println(信号量发生错误);e.printStackTrace();System.exit(1);}countDownLatch.countDown();});}countDownLatch.await();executorService.shutdown();System.out.println(所有线程格式化日期成功);}
}运行结果
java.lang.NumberFormatException: For input string:
线程pool-1-thread-1 格式化日期失败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:2051)at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:1869)at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1514)at java.text.DateFormat.parse(DateFormat.java:364)at com.xysd.concurrent.lab06.SimpleDateFormatTest01.lambda$main$0(SimpleDateFormatTest01.java:72)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)原因
//SimpleDateFormat
public Date parse(String text, ParsePosition pos) {CalendarBuilder calb new CalendarBuilder();Date parsedDate;try {//TODOparsedDate calb.establish(calendar).getTime();if (ambiguousYear[0]) {if (parsedDate.before(defaultCenturyStart)) {parsedDate calb.addYear(100).establish(calendar).getTime();}}}catch (IllegalArgumentException e) {pos.errorIndex start;pos.index oldStart;return null;}return parsedDate;}//CalendarBuilder
//clear()和set()这两个方法执行不是原子操作所以造成线程不安全
Calendar establish(Calendar cal) {boolean weekDate isSet(WEEK_YEAR) field[WEEK_YEAR] field[YEAR];if (weekDate !cal.isWeekDateSupported()) {// Use YEAR insteadif (!isSet(YEAR)) {set(YEAR, field[MAX_FIELD WEEK_YEAR]);}weekDate false;}//这里线clearcal.clear();for (int stamp MINIMUM_USER_STAMP; stamp nextStamp; stamp) {for (int index 0; index maxFieldIndex; index) {if (field[index] stamp) {//然后再setcal.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;}解决方案一 方法局部变量
public class SimpleDateFormatTest01 {//执行总次数private static final int EXECUTE_COUNT 1000;//同时运行的线程数量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(线程 Thread.currentThread().getName() 格式化日期失败);e.printStackTrace();System.exit(1);} catch (NumberFormatException e) {System.out.println(线程 Thread.currentThread().getName() 格式化日期失败);e.printStackTrace();System.exit(1);}semaphore.release();} catch (InterruptedException e) {System.out.println(信号量发生错误);e.printStackTrace();System.exit(1);}countDownLatch.countDown();});}countDownLatch.await();executorService.shutdown();System.out.println(所有线程格式化日期成功);}
}解决方案二 使用synchronized锁
public class SimpleDateFormatTest01 {//执行总次数private static final int EXECUTE_COUNT 1000;//同时运行的线程数量private static final int THREAD_COUNT 20;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(线程 Thread.currentThread().getName() 格式化日期失败);e.printStackTrace();System.exit(1);} catch (NumberFormatException e) {System.out.println(线程 Thread.currentThread().getName() 格式化日期失败);e.printStackTrace();System.exit(1);}semaphore.release();} catch (InterruptedException e) {System.out.println(信号量发生错误);e.printStackTrace();System.exit(1);}countDownLatch.countDown();});}countDownLatch.await();executorService.shutdown();System.out.println(所有线程格式化日期成功);}
}解决方案三 Lock锁
public class SimpleDateFormatTest01 {//执行总次数private static final int EXECUTE_COUNT 1000;//同时运行的线程数量private static final int THREAD_COUNT 20;private static SimpleDateFormat simpleDateFormat new SimpleDateFormat(yyyy-MM-dd);private static Lock lock new ReentrackLock();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(线程 Thread.currentThread().getName() 格式化日期失败);e.printStackTrace();System.exit(1);} catch (NumberFormatException e) {System.out.println(线程 Thread.currentThread().getName() 格式化日期失败);e.printStackTrace();System.exit(1);}finally{lock.unlock();}semaphore.release();} catch (InterruptedException e) {System.out.println(信号量发生错误);e.printStackTrace();System.exit(1);}countDownLatch.countDown();});}countDownLatch.await();executorService.shutdown();System.out.println(所有线程格式化日期成功);}
}解决方案四 ThreadLocal
public class SimpleDateFormatTest01 {//执行总次数private static final int EXECUTE_COUNT 1000;//同时运行的线程数量private static final int THREAD_COUNT 20;//SimpleDateFormat对象private static SimpleDateFormat simpleDateFormat new SimpleDateFormat(yyyy-MM-dd);//本地线程private static ThreadLocalSimpleDateFormat threadLocal new ThreadLocalSimpleDateFormat() {Overrideprotected SimpleDateFormat initialValue() {return new SimpleDateFormat(yyyy-MM-dd);}};private static DateFormat getDateFormat() {SimpleDateFormat 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(线程 Thread.currentThread().getName() 格式化日期失败);e.printStackTrace();System.exit(1);} catch (NumberFormatException e) {System.out.println(线程 Thread.currentThread().getName() 格式化日期失败);e.printStackTrace();System.exit(1);}semaphore.release();} catch (InterruptedException e) {System.out.println(信号量发生错误);e.printStackTrace();System.exit(1);}countDownLatch.countDown();});}countDownLatch.await();executorService.shutdown();System.out.println(所有线程格式化日期成功);}}解决方案五 DateTimeFormatter
public class SimpleDateFormatTest01 {//执行总次数private static final int EXECUTE_COUNT 1000;//同时运行的线程数量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(线程 Thread.currentThread().getName() 格式化日期失败);e.printStackTrace();System.exit(1);}semaphore.release();} catch (InterruptedException e) {System.out.println(信号量发生错误);e.printStackTrace();System.exit(1);}countDownLatch.countDown();});}countDownLatch.await();executorService.shutdown();System.out.println(所有线程格式化日期成功);}
}总结
在高并发情况下推荐使用ThreadLocal或DateTimeFormatter
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/926369.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!