java – 在测试中重现SimpleDateFormat非线程安全性
发布时间:2020-12-15 05:20:46 所属栏目:Java 来源:网络整理
导读:我有一个应用程序,它不时在日志中有这个堆栈跟踪: java.lang.ArrayIndexOutOfBoundsException: 514 at sun.util.calendar.BaseCalendar.getCalendarDateFromFixedDate(BaseCalendar.java:436) at java.util.GregorianCalendar.computeFields(GregorianCalen
我有一个应用程序,它不时在日志中有这个堆栈跟踪:
java.lang.ArrayIndexOutOfBoundsException: 514 at sun.util.calendar.BaseCalendar.getCalendarDateFromFixedDate(BaseCalendar.java:436) at java.util.GregorianCalendar.computeFields(GregorianCalendar.java:2081) at java.util.GregorianCalendar.computeFields(GregorianCalendar.java:1996) at java.util.Calendar.complete(Calendar.java:1312) at java.util.Calendar.get(Calendar.java:1093) at java.text.SimpleDateFormat.subFormat(SimpleDateFormat.java:917) at java.text.SimpleDateFormat.format(SimpleDateFormat.java:824) at java.text.SimpleDateFormat.format(SimpleDateFormat.java:796) at java.text.DateFormat.format(DateFormat.java:314) at me.myself.i.Message.toString(Message.java:203) at java.lang.String.valueOf(String.java:2615) at java.lang.StringBuilder.append(StringBuilder.java:116) 我认为这个问题可能存在于某些方面: public class Message{ private transient DateFormat logDateFormat; @Override public String toString() { final StringBuilder result = new StringBuilder(getClass().getSimpleName()); result.append("Time=").append(logDateFormat.format(new Date(getExpireTime()))); return result.toString(); } } 我认为多个线程同时调用toString(),但我在本地机器上重现这个问题: @Before public void setUp() { message = new Message(); pool = Executors.newFixedThreadPool(numOfThreads); } @Test public void multiThreadTest() { for (int i=0; i<numOfThreads; i++) { TestJob j = new TestJob(message); pool.submit(j); } pool.shutdown(); while(!pool.isTerminated()){ } } class TestJob implements Runnable{ private Message message; private int n=100; public TestJob(Message message) { this.message= message; } public void run() { for (int i=0; i<n; i++) { try{ System.out.println(message.toString()); } catch(Exception e){ e.printStackTrace(); } } } } 如何编写正确的junit测试来重现此问题? 解决方法
由于我的第一次测试没有重现你的问题,试试这个
final SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd"); ExecutorService ex = Executors.newFixedThreadPool(1000); for (;;) { ex.execute(new Runnable() { public void run() { try { f.format(new Date(new Random().nextLong())); } catch (Exception e) { e.printStackTrace(); System.exit(1); } }; }); } 这需要时间,但最后我得到了 java.lang.ArrayIndexOutOfBoundsException: 3144942 at sun.util.calendar.BaseCalendar.getCalendarDateFromFixedDate(BaseCalendar.java:454) at java.util.GregorianCalendar.computeFields(GregorianCalendar.java:2333) at java.util.GregorianCalendar.computeFields(GregorianCalendar.java:2248) at java.util.Calendar.complete(Calendar.java:1560) at java.util.Calendar.get(Calendar.java:1162) at java.text.SimpleDateFormat.subFormat(SimpleDateFormat.java:1093) at java.text.SimpleDateFormat.format(SimpleDateFormat.java:978) at java.text.SimpleDateFormat.format(SimpleDateFormat.java:948) at java.text.DateFormat.format(DateFormat.java:336) at Test1$1.run(Test1.java:17) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603) at java.lang.Thread.run(Thread.java:722) (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |