天天看點

DateTimeFormatter和SimpleDateFormat的parse性能對比1.單線程性能對比2.多線程性能對比3.非線程安全SimpleDateFormat4.線程安全DateTimeFormatter5.結論

文章目錄

  • 1.單線程性能對比
  • 2.多線程性能對比
  • 3.非線程安全SimpleDateFormat
  • 4.線程安全DateTimeFormatter
  • 5.結論

1.單線程性能對比

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.text.SimpleDateFormat;
public class Test{
	public static void main(String[] args) {
    	String time = "20171231235959";
    	int count = 1000000;
    	String formats = "yyyyMMddHHmmss";
    	long s = System.nanoTime();
    	for(int i = 0; i < count ; i ++ ) {
        	DateTimeFormatter dtf = DateTimeFormatter.ofPattern(formats);
    		LocalDateTime.parse(time, dtf);
    	}
    	System.out.println( "DateTimeFormatter:\t" + ( System.nanoTime() - s) );
    	
    	try {
        	s = System.nanoTime();
        	for(int i = 0; i < count ; i ++ ) {
        		SimpleDateFormat sdf = new SimpleDateFormat(formats);
        		sdf.parse(time);
        	}
        	System.out.println( "SimpleDateFormat:\t" + ( System.nanoTime() - s) );
    	}catch (Exception e) {
			e.printStackTrace();
		}
    }
}
                

結果

DateTimeFormatter:	1075056771
SimpleDateFormat:	1777736489
                

2.多線程性能對比

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.text.SimpleDateFormat;
public class Test{
	public static void main(String[] args)  throws Exception{
    	for(int i = 0; i < 1000; i ++ ) {
        	dateThreadTest();
    	}
    }
    
    public static void dateThreadTest() throws InterruptedException {
    	List<Long> simlist = new ArrayList<>();
    	
    	int count = 2000;
    	CountDownLatch countDownLatch = new CountDownLatch(count);
    	
    	String time = "20171231235959";
    	String formats = "yyyyMMddHHmmss";

    	
    	//DateTimeFormatter
    	CountDownLatch countDownLatch_fmt = new CountDownLatch(count);
    	List<Long> fmtlist = new ArrayList<>();
    	DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(formats);
    	Runnable fmtrun = () -> {
    		long s = System.nanoTime();
    		for( int i = 0; i < 500 ; i ++ ) {
    			try {
    				LocalDateTime.parse(time, dateTimeFormatter);
				} catch (Exception e) {
					e.printStackTrace();
				}
    		}
    		long e = System.nanoTime() - s;
    		synchronized(fmtlist) {
        		fmtlist.add( e );
    		}
    		countDownLatch_fmt.countDown();
    	};

    	
    	for(int i = 0; i < count ; i ++ ) {
    		new Thread(fmtrun).start();
    	}
    	countDownLatch_fmt.await();
    	
    	long fmtsum = 0;
    	for(Long fmtl : fmtlist ) {
    		fmtsum += fmtl;
    	}
    	int fmtsize = fmtlist.size();
    	long fmtavg = fmtsum / fmtsize;
    	
    	System.out.println("DateTimeFormatter:\t" + fmtavg+ "-size:" + fmtsize);
    	
    	//SimpleDateFormat
    	Runnable simrun = () -> {
    		long s = System.nanoTime();
    		SimpleDateFormat simpleDateFormat = new SimpleDateFormat(formats);
    		for( int i = 0; i < 500 ; i ++ ) {
    			try {
					simpleDateFormat.parse(time);
				} catch (ParseException e) {
					e.printStackTrace();
				}
    		}
    		long e = System.nanoTime() - s;
    		synchronized (simlist) {
        		simlist.add( e );
			}
    		countDownLatch.countDown();
    	};

    	
    	for(int i = 0; i < count ; i ++ ) {
    		new Thread(simrun).start();
    	}
    	countDownLatch.await();
    	
    	long simsum = 0;
    	int simsize = simlist.size();
    	for(Long siml : simlist) {
    		simsum += siml;
    	}
    	long simavg = simsum / simsize;
    	
    	System.out.println("SimpleDateFormat:\t" + simavg + "-size:" + simsize);
    }
}
                

結果片斷

DateTimeFormatter:	320070-size:2000
SimpleDateFormat:	1579198-size:2000
DateTimeFormatter:	1149074-size:2000
SimpleDateFormat:	5590201-size:2000
DateTimeFormatter:	388116-size:2000
SimpleDateFormat:	1444295-size:2000
DateTimeFormatter:	391754-size:2000
SimpleDateFormat:	2403905-size:2000
DateTimeFormatter:	579022-size:2000
SimpleDateFormat:	1405484-size:2000
DateTimeFormatter:	575568-size:2000
SimpleDateFormat:	1565345-size:2000
DateTimeFormatter:	683145-size:2000
SimpleDateFormat:	2243927-size:2000
DateTimeFormatter:	2521980-size:2000
SimpleDateFormat:	3564548-size:2000
DateTimeFormatter:	452000-size:2000
SimpleDateFormat:	4381109-size:2000
DateTimeFormatter:	329263-size:2000
SimpleDateFormat:	476896-size:2000
DateTimeFormatter:	337858-size:2000
SimpleDateFormat:	510113-size:2000
DateTimeFormatter:	945077-size:2000
SimpleDateFormat:	1093366-size:2000
DateTimeFormatter:	854730-size:2000
SimpleDateFormat:	649053-size:2000
DateTimeFormatter:	379670-size:2000
SimpleDateFormat:	4156187-size:2000
DateTimeFormatter:	1214384-size:2000
SimpleDateFormat:	2089635-size:2000
DateTimeFormatter:	1309359-size:2000
SimpleDateFormat:	1360002-size:2000
DateTimeFormatter:	403218-size:2000
SimpleDateFormat:	643400-size:2000
DateTimeFormatter:	656442-size:2000
SimpleDateFormat:	12865579-size:2000
DateTimeFormatter:	1357402-size:2000
SimpleDateFormat:	556662-size:2000
DateTimeFormatter:	327016-size:2000
SimpleDateFormat:	689728-size:2000
DateTimeFormatter:	371160-size:2000
SimpleDateFormat:	852151-size:2000
DateTimeFormatter:	1296601-size:2000
SimpleDateFormat:	3495863-size:2000
DateTimeFormatter:	1382038-size:2000
SimpleDateFormat:	557998-size:2000
DateTimeFormatter:	408569-size:2000
SimpleDateFormat:	2498495-size:2000
DateTimeFormatter:	1658727-size:2000
SimpleDateFormat:	768303-size:2000
DateTimeFormatter:	412967-size:2000
SimpleDateFormat:	476698-size:2000
DateTimeFormatter:	335527-size:2000
SimpleDateFormat:	469686-size:2000
DateTimeFormatter:	568296-size:2000
SimpleDateFormat:	559510-size:2000
DateTimeFormatter:	398402-size:2000
SimpleDateFormat:	468114-size:2000
DateTimeFormatter:	538794-size:2000
SimpleDateFormat:	523629-size:2000
DateTimeFormatter:	427579-size:2000
SimpleDateFormat:	2054706-size:2000
DateTimeFormatter:	424820-size:2000
SimpleDateFormat:	552673-size:2000
DateTimeFormatter:	418098-size:2000
SimpleDateFormat:	996775-size:2000
DateTimeFormatter:	323411-size:2000
SimpleDateFormat:	826378-size:2000
DateTimeFormatter:	329768-size:2000
SimpleDateFormat:	664224-size:2000
DateTimeFormatter:	334381-size:2000
SimpleDateFormat:	577824-size:2000
DateTimeFormatter:	670466-size:2000
SimpleDateFormat:	3654294-size:2000
DateTimeFormatter:	348893-size:2000
SimpleDateFormat:	1214426-size:2000
DateTimeFormatter:	961402-size:2000
SimpleDateFormat:	625569-size:2000
DateTimeFormatter:	318604-size:2000
SimpleDateFormat:	1610296-size:2000
DateTimeFormatter:	395029-size:2000
SimpleDateFormat:	1112620-size:2000
DateTimeFormatter:	317822-size:2000
SimpleDateFormat:	6746071-size:2000
                

3.非線程安全SimpleDateFormat

import java.text.SimpleDateFormat;
public class Test{
	public static void main(String[] args) {
    	SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
    	String[] dates = {"20180101120000","20180912010000","20181101210000"};
    	
    	Runnable runnable = () -> {
    		for(int i =0; i < 500; i ++ ) {
    			String string = dates[i % 3];
    			try {
    				if( string.length() > 0 ) {
    					Date date = simpleDateFormat.parse(string);
    					String stringnew = simpleDateFormat.format(date);
    					//對同一時間字串進行parse和fromat後比較是否一樣
    					boolean issame = string.equals(stringnew);
    					if( !issame ) {//前後不一樣,進行輸出
    						System.out.println(issame + "-" + string + "-" + stringnew);
    						break;
    					}
    				}
				} catch (Exception e) {
					e.printStackTrace();
				}
    			
    		}
    	};
    	
    	for(int i = 0; i < 10000; i ++ ) {
    		new Thread(runnable).start();
    	}
    }
}
                

SimpleDateFormat多線程-結果片斷

false-20181101210000-00211101210000
	at com.cgs.hb.TestMain.lambda$0(TestMain.java:56)
	at java.lang.Thread.run(Thread.java:748)
java.lang.NumberFormatException: For input string: "1."
	at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
	at java.lang.Long.parseLong(Long.java:589)
	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:1867)
	at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1514)
	at java.text.DateFormat.parse(DateFormat.java:364)
	at com.cgs.hb.TestMain.lambda$0(TestMain.java:56)
	at java.lang.Thread.run(Thread.java:748)
java.lang.NumberFormatException: multiple points
	at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1890)
	at sun.misc.FloatingDecimal.parseDouble(FloatingDecimal.java:110)
	at java.lang.Double.parseDouble(Double.java:538)
	at java.text.DigitList.getDouble(DigitList.java:169)
	at java.text.DecimalFormat.parse(DecimalFormat.java:2089)
	at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:2160)
	at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1514)
	at java.text.DateFormat.parse(DateFormat.java:364)
	at com.cgs.hb.TestMain.lambda$0(TestMain.java:56)
	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:2160)
	at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1514)
	at java.text.DateFormat.parse(DateFormat.java:364)
	at com.cgs.hb.TestMain.lambda$0(TestMain.java:56)
	at java.lang.Thread.run(Thread.java:748)
false-20180101120000-20181101210000
                

4.線程安全DateTimeFormatter

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class Test{
	public static void main(String[] args) {

    	DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
    	String[] dates = {"20180101120000","20180912010000","20181101210000"};
    	
    	Runnable runnable = () -> {
    		for(int i =0; i < 500; i ++ ) {
    			String string = dates[i % 3];
    			try {
    				if( string.length() > 0 ) {
    					LocalDateTime date = LocalDateTime.parse(string, dateTimeFormatter);
    					String stringnew = date.format(dateTimeFormatter);
    					//對同一時間字串進行parse和fromat後比較是否一樣
    					boolean issame = string.equals(stringnew);
    					if( !issame ) {//前後不一樣,進行輸出
    						System.out.println(issame + "-" + string + "-" + stringnew);
    						break;
    					}
    				}
				} catch (Exception e) {
					e.printStackTrace();
				}
    			
    		}
    	};
    	
    	for(int i = 0; i < 10000; i ++ ) {
    		new Thread(runnable).start();
    	}
    }
}
                

DateTimeFormatter多線程-結果片斷

無輸出
                

5.結論

1.DateTimeFormatter線程安全,SimpleDateFormat非線程安全

2.單線程環境下DateTimeFormatter+LocalDateTime的parse性能比SimpleDateFormat的parse性能高

3.多線程環境下DateTimeFormatter作為共享變量時,大部分情況下性能比SimpleDateFormat高(因為多線程環境的複雜性,此結論不一定準确)