Java DateFormat 병행 실현
DateFormat 。 , 。
이번 테스트 를 통 해 얻 은 경험 들:
/**
* 。
*
* @author Bert Lee
* @version 2014-8-16
*/
public interface DateFormattable {
/**
*
*/
String PATTERN = "yyyy-MM-dd";
/**
* Formats a Date into a date/time string.
*
* @param date
* @return
* @see java.text.DateFormat#format(Date)
*/
String format(Date date);
/**
* Parses text from the beginning of the given string to produce a date.
*
* @param source
* @return
* @throws ParseException
* @see java.text.DateFormat#parse(String)
*/
Date parse(String source) throws ParseException;
}
/**
* {@link DateFormat} wrapper.
*
* @author Bert Lee
* @version 2014-8-16
*/
public class DateFormatWrapper implements DateFormattable {
private final DateFormat format;
public DateFormatWrapper() {
this(PATTERN);
}
public DateFormatWrapper(String pattern) {
this.format = new SimpleDateFormat(pattern);
}
/**
* <font color="red"> UT ,format ( StringBuffer )!</font>
*/
@Override
public String format(Date date) {
return this.format.format(date);
}
/**
* <font color="red"> UT ,parse ( )!</font>
*/
@Override
public Date parse(String source) throws ParseException {
return this.format.parse(source);
}
}
/**
* Date parse task.
*
* @author Bert Lee
* @version 2014-8-16
*/
public class DateParseCallable implements Callable<Date> {
private DateFormattable formatter;
private String source;
public DateParseCallable(DateFormattable formatter, String source) {
this.formatter = formatter;
this.source = source;
}
@Override
public Date call() throws Exception {
return this.formatter.parse(source);
}
}
/**
* Concurrent thread {@link java.util.concurrent.Executor Executor} wrapper.
*
* @author Bert Lee
* @version 2014-8-16
*/
public class ConcurrentThreadExecutorWrapper<T> {
private ExecutorService executor;
private Callable<T> task;
private List<Future<T>> results;
private TestScale runTimes;
public ConcurrentThreadExecutorWrapper(Callable<T> task) {
this(task, TestScale.BASIC);
}
public ConcurrentThreadExecutorWrapper(Callable<T> task, TestScale runTimes) {
// pool with 5 threads
this.executor = Executors.newFixedThreadPool(5);
this.task = task;
this.runTimes = runTimes;
}
public void run() {
results = new ArrayList<Future<T>>();
// perform 10 times date conversions
for (int i = 0; i < runTimes.getValue(); i++) {
results.add(executor.submit(task));
}
executor.shutdown();
}
public void printResults() throws Exception {
this.run();
// look at the results
for (Future<T> result : results) {
out.println(result.get());
}
}
}
/**
* Test for {@link ConcurrentThreadExecutorWrapper}.
* <p>
* <a href="http://stackoverflow.com/questions/4021151/java-dateformat-is-not-threadsafe-what-does-this-leads-to">
* “Java DateFormat is not thread-safe” what does this leads to?</a>
*
* @author Bert Lee
* @version 2014-8-16
*/
public class DateFormatExecutorTest {
//
private static final String pattern = "yyyy-MM-dd HH:mm";
/*
* UT ,DateFormat format ( StringBuffer ), parse ( )!
* DateFormat parse , !
*
* DateFormatThreadLocal、DateTimeFormatterWrapper FastDateFormatWrapper 。
*/
@Test(dataProvider = "parse", groups = "parse")
public void parse(DateFormattable formatter, String source) throws Exception {
Callable<Date> task = new DateParseCallable(formatter, source);
ConcurrentThreadExecutorWrapper<Date> executor = new ConcurrentThreadExecutorWrapper<Date>(task);
out.println(formatter.getClass().getSimpleName() + " parse result:");
executor.printResults();
}
@DataProvider(name = "parse")
protected static final Object[][] parseTestData() {
Object[][] testData = new Object[][] {
// { new DateFormatWrapper(pattern), "2014-08-16 08:23:07" }, // , , !
{ new DateFormatThreadLocal(pattern), "2014-08-16 08:23:07" },
{ new DateTimeFormatterWrapper(pattern), "2014-08-16 08:23" },
{ new FastDateFormatWrapper(pattern), "2014-08-16 08:23:07" },
};
return testData;
}
@Test(dataProvider = "format", groups = "format")
public void format(DateFormattable formatter) throws Exception {
Date date = new Date();
Callable<String> task = new DateFormatCallable(formatter, date);
ConcurrentThreadExecutorWrapper<String> executor = new ConcurrentThreadExecutorWrapper<String>(task);
out.println(formatter.getClass().getSimpleName() + " format result:");
executor.printResults();
}
@DataProvider(name = "format")
protected static final Object[][] formatTestData() {
Object[][] testData = new Object[][] {
{ new DateFormatWrapper(pattern) },
{ new DateFormatThreadLocal(pattern) },
{ new DateTimeFormatterWrapper(pattern) },
{ new FastDateFormatWrapper(pattern) },
};
return testData;
}
}
병발 문 제 를 해결 하기 위해 StackOverflow 의 이 글 인 “Java DateFormat is not thread-safe” what does this leads to? 과 Java Best Practices – DateFormat in a Multithreading Environment 을 참고 하여 이 를 바탕 으로 재 구성 및 성능 테스트 를 실시 했다.글 은 세 가지 해결 방안 을 제공 했다.
ThreadLocal :
ThreadLocal
변 수 를 바탕 으로 소지 DateFormat
대상 /**
* {@link DateFormat} thread-local.
*
* @author Bert Lee
* @version 2014-8-16
*/
public class DateFormatThreadLocal implements DateFormattable {
private final ThreadLocal<DateFormat> format;
public DateFormatThreadLocal() {
this(PATTERN);
}
public DateFormatThreadLocal(final String pattern) {
this.format = new ThreadLocal<DateFormat>() {
@Override
protected DateFormat initialValue() {
return new SimpleDateFormat(pattern);
}
};
}
@Override
public String format(Date date) {
return this.format.get().format(date);
}
@Override
public Date parse(String source) throws ParseException {
return this.format.get().parse(source);
}
}
/**
* {@link DateTimeFormatter} wrapper.
*
* @author Bert Lee
* @version 2014-8-19
*/
public class DateTimeFormatterWrapper implements DateFormattable {
private final DateTimeFormatter format;
public DateTimeFormatterWrapper() {
this(PATTERN);
}
public DateTimeFormatterWrapper(String pattern) {
this.format = DateTimeFormat.forPattern(pattern);
}
@Override
public String format(Date date) {
return this.format.print(date.getTime());
}
/**
* <font color="red"> , !</font>
*/
@Override
public Date parse(String source) throws ParseException {
DateTime dt = this.format.parseDateTime(source);
return dt.toDate();
}
}
/**
* {@link FastDateFormat} is a fast and thread-safe version of
* {@link java.text.SimpleDateFormat}.<p>
*
* FastDateFormat implements the behavior of Java 7.
*
* @author Bert Lee
* @version 2014-8-26
*/
public class FastDateFormatWrapper implements DateFormattable {
private final FastDateFormat format;
public FastDateFormatWrapper() {
this(PATTERN);
}
public FastDateFormatWrapper(String pattern) {
this.format = FastDateFormat.getInstance(pattern);
}
@Override
public String format(Date date) {
return this.format.format(date);
}
@Override
public Date parse(String source) throws ParseException {
return this.format.parse(source);
}
}
public class DateFormatExecutorTest {
//
private static final String pattern = "yyyy-MM-dd HH:mm";
/*
* 500 +5 ,
* format ,DateTimeFormatterWrapper ,FastDateFormatWrapper ,DateFormatThreadLocal ;
* parse , 。
*/
@Test(dataProvider = "profileParse", groups = "profile")
public void profileParse(DateFormattable formatter, String source) throws Exception {
String className = formatter.getClass().getSimpleName() + "'s parse";
RunTimeStats timeStats = new RunTimeStats(className);
Callable<Date> task = new DateParseCallable(formatter, source);
ConcurrentThreadExecutorWrapper<Date> executor = new ConcurrentThreadExecutorWrapper<Date>(task, TestScale.SMALL);
executor.run();
timeStats.print();
}
@DataProvider(name = "profileParse")
protected static final Object[][] profileParseTestData() {
Object[][] testData = new Object[][] {
{ new DateFormatThreadLocal(pattern), "2014-08-16 08:23:07"},
{ new DateTimeFormatterWrapper(pattern), "2014-08-16 08:23" },
{ new FastDateFormatWrapper(pattern), "2014-08-16 08:23:07" },
};
return testData;
}
@Test(dataProvider = "profileFormat", groups = "profile")
public void profileFormat(DateFormattable formatter) throws Exception {
String className = formatter.getClass().getSimpleName() + "'s format";
RunTimeStats timeStats = new RunTimeStats(className);
Date date = new Date();
Callable<String> task = new DateFormatCallable(formatter, date);
ConcurrentThreadExecutorWrapper<String> executor = new ConcurrentThreadExecutorWrapper<String>(task, TestScale.MIDDLE);
executor.run();
timeStats.print();
}
@DataProvider(name = "profileFormat")
protected static final Object[][] profileFormatTestData() {
Object[][] testData = new Object[][] {
{ new DateFormatThreadLocal(pattern) },
{ new DateTimeFormatterWrapper(pattern) },
{ new FastDateFormatWrapper(pattern) },
};
return testData;
}
}
온전한 원본 은 첨부 파일 참조 ~
즐 거 운 시간 보 내세 요! ^ ^
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Is Eclipse IDE dying?In 2014 the Eclipse IDE is the leading development environment for Java with a market share of approximately 65%. but ac...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.