jdk8的时间API是线程安全的,可以看下面的案例测试

package cn.wcj.jdk8.lambda.test;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 
* <p>Title:DateFormatThreadLocal </p>
* <p>Description: 线程安全时间格式化</p>
* <p>Company:Software College </p> 
* @author SuccessKey(WangCJ)
* @date 2017年6月21日 上午9:21:21
 */
public class DateFormatThreadLocal {

    private static final ThreadLocal<DateFormat> THREAD_DF=new ThreadLocal<DateFormat>(){

        @Override
        public DateFormat initialValue() {
            return new SimpleDateFormat("yyyyMMdd")  ;
        }

    }  ;


    public static final Date convert(String source)throws Exception{
           return THREAD_DF.get().parse(source)   ;
    }



}
package cn.wcj.jdk8.lambda.test;


import java.text.SimpleDateFormat;
import java.time.DayOfWeek;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.Period;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

import org.junit.Test;
/**
 * 
* <p>Title:DateTest </p>
* <p>Description:测试JDK8新时间API </p>
* <p>Company:Software College </p> 
* @author SuccessKey(WangCJ)
* @date 2017年6月21日 上午9:05:59
 */
public class DateTest {

    //JDK7的时间API存在线程安全问题演示
    //结果1 出现抢占造成结果不正确
    //  Wed Jun 21 00:00:00 CST 2017
    //  Wed Jun 21 00:00:00 CST 6017
    //  Wed Jun 21 00:00:00 CST 6017
    //  Wed Jun 21 00:00:00 CST 2017
    //  Wed Jun 21 00:00:00 CST 2017
    //  Fri Jun 21 00:00:00 CST 2120
    //  Sun Jun 21 00:00:00 CST 6201
    //  Wed Jun 21 00:00:00 CST 2017
    //  Wed Jun 21 00:00:00 CST 2017
    //  Wed Jun 21 00:00:00 CST 2017
    //  Sat Sep 21 00:00:00 CST 2193
    //结果2  线程安全问题JUC
    //java.util.concurrent.ExecutionException: java.lang.NumberFormatException
    @Test
    public void test1() throws Exception {
        SimpleDateFormat sdf=new SimpleDateFormat("yyyyMMdd")   ;
        Callable<Date> task=new Callable<Date>() {

            @Override
            public Date call() throws Exception {
                return sdf.parse("20170621");
            }

        };
        ExecutorService threadPool = Executors.newFixedThreadPool(10);
        List<Future<Date>> resultList = new ArrayList<Future<Date>>();
        for(int x=0;x<12;x++)
            resultList.add(threadPool.submit(task))   ;
        for (Future<Date> future : resultList) {
            System.out.println(future.get());
        }
        threadPool.shutdown();
    }

    //使用ThreadLocal改进JDK7时间线程安全问题
    //运行结果
    //  Wed Jun 21 00:00:00 CST 2017
    //  Wed Jun 21 00:00:00 CST 2017
    //  Wed Jun 21 00:00:00 CST 2017
    //  Wed Jun 21 00:00:00 CST 2017
    //  Wed Jun 21 00:00:00 CST 2017
    //  Wed Jun 21 00:00:00 CST 2017
    //  Wed Jun 21 00:00:00 CST 2017
    //  Wed Jun 21 00:00:00 CST 2017
    //  Wed Jun 21 00:00:00 CST 2017
    //  Wed Jun 21 00:00:00 CST 2017
    @Test
    public void test2() throws Exception{
        Callable<Date> task=new Callable<Date>() {

            @Override
            public Date call() throws Exception {
                return DateFormatThreadLocal.convert("20170621") ;
            }

        };
        ExecutorService threadPool = Executors.newFixedThreadPool(10);
        List<Future<Date>> resultList = new ArrayList<Future<Date>>();
        for (int i = 0; i <10; i++) 
            resultList.add(threadPool.submit(task)) ;
        for (Future<Date> future : resultList) 
            System.out.println(future.get());
        threadPool.shutdown();  
    }

    //JDK8线程安全
    //  2017-06-21
    //  2017-06-21
    //  2017-06-21
    //  2017-06-21
    //  2017-06-21
    //  2017-06-21
    //  2017-06-21
    //  2017-06-21
    //  2017-06-21
    //  2017-06-21
    @Test
    public void test3()throws Exception{
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyyMMdd");
        Callable<LocalDate> task=()->LocalDate.parse("20170621", dtf)   ;
        ExecutorService threadPool = Executors.newFixedThreadPool(10);
        List<Future<LocalDate>> resultList = new ArrayList<Future<LocalDate>>();
        for (int i = 0; i < 10; i++) 
            resultList.add(threadPool.submit(task))   ;
        int len=resultList.size()   ;
        for (int i = 0; i < len; i++) {
            System.out.println(resultList.get(i).get());
        }
        threadPool.shutdown();   
    }

    //LocalDate、LocalTime、LocalDateTime
    @Test
    public void test4()throws Exception{
          LocalDateTime localDateTime = LocalDateTime.now()  ;
          System.out.println(localDateTime)  ;
          System.out.println("-------------------------");
          LocalDateTime localDateTime2 = LocalDateTime.of(2017, 6, 21, 10, 29,30);
          System.out.println(localDateTime2) ;
          System.out.println("-------------------------");
          LocalDateTime plusYears = localDateTime2.plusYears(1);
          System.out.println(plusYears);
          System.out.println("-------------------------");
          LocalDateTime minusMonths = localDateTime2.minusMonths(3);
          System.out.println(minusMonths);
          System.out.println("-------------------------");
          System.out.println(localDateTime.getYear());
          System.out.println(localDateTime.getMonthValue());
          System.out.println(localDateTime.getDayOfMonth());
          System.out.println(localDateTime.getHour());
          System.out.println(localDateTime.getMinute());
          System.out.println(localDateTime.getSecond());
    }

    // Instant : 时间戳。 (使用 Unix 元年  19701100:00:00 所经历的毫秒值)
    @Test
    public void test5() {
        Instant now = Instant.now()  ; //默认使用 UTC 时区
        System.out.println(now)      ;
        OffsetDateTime offsetDateTime = now.atOffset(ZoneOffset.ofHours(8)) ;
        System.out.println(offsetDateTime) ;
        System.out.println(now.getNano())  ;
        Instant now2 = Instant.ofEpochSecond(5);
        System.out.println(now2);
    }

    //Duration : 用于计算两个“时间”间隔
    //Period : 用于计算两个“日期”间隔
    @Test
    public void test6() throws Exception{
           Instant ins1 = Instant.now();
           Thread.sleep(1000) ;
           Instant ins2 = Instant.now();
           System.out.println(Duration.between(ins1, ins2).getSeconds());
           System.out.println("---------------------")  ;
           LocalDate ld1 = LocalDate.of(2014, 9, 5)   ;
           LocalDate ld2 = LocalDate.now()  ;
           Period period = Period.between(ld1, ld2);
           System.out.println(period.getYears());
           System.out.println(period.getMonths());
           System.out.println(period.getDays());
    }

    //TemporalAdjuster : 时间校正器
    @Test
    public void test7() {
          LocalDateTime localDateTime = LocalDateTime.now()  ;
          System.out.println(localDateTime);     
          LocalDateTime localDateTime2 = localDateTime.withDayOfMonth(10) ;
          System.out.println(localDateTime2);
          LocalDateTime localDateTime3 = localDateTime.with(TemporalAdjusters.next(DayOfWeek.FRIDAY));
          System.out.println(localDateTime3);
          //自定义:下一个工作日
          LocalDateTime localDateTime5 = localDateTime.with((l)->{
              LocalDateTime localDateTime4 = (LocalDateTime) l ;
              DayOfWeek dayOfWeek=localDateTime4.getDayOfWeek();
            if(dayOfWeek.equals(DayOfWeek.FRIDAY)){
                return localDateTime4.plusDays(3);
            }else if(dayOfWeek.equals(DayOfWeek.SATURDAY)){
                return localDateTime4.plusDays(2);
            }else{
                return localDateTime4.plusDays(1);
            }
          });
          System.out.println(localDateTime5);
    }

    //DateTimeFormatter : 解析和格式化日期或时间
    @Test
    public void test8() {
        DateTimeFormatter dtf = DateTimeFormatter.ISO_LOCAL_DATE  ;
        LocalDateTime localDateTime = LocalDateTime.now()   ;
        String fmt = localDateTime.format(dtf)   ;
        System.out.println(fmt)  ;
        System.out.println("------------------------")    ;
        DateTimeFormatter dtf2 = DateTimeFormatter
                                      .ofPattern("yyyy年MM月dd日 HH:mm:ss E") ;
        LocalDateTime localDateTime2 = LocalDateTime.now()   ;
        System.out.println(localDateTime2);
        String fmt2 = localDateTime2.format(dtf2)   ;
        System.out.println(fmt2) ;
        System.out.println("------------------------")    ;
        LocalDateTime parse = LocalDateTime.parse(fmt2, dtf2)  ;
        System.out.println(parse)  ;
    }

    //Asia/Shanghai
    @Test
    public void test9(){
        Set<String> availableZoneIds = ZoneId.getAvailableZoneIds();
        availableZoneIds.stream()
                        .filter((t)->t.contains("Asia"))
                        .sorted()
                        .forEach(System.out::println);
    }

    @Test
    public void test10(){
         LocalDateTime localDateTime = LocalDateTime.now(ZoneId.of("Asia/Shanghai"))  ;
         System.out.println(localDateTime)  ;
    } 


}