자바 8 새로운 기능 의 스 레 드 보안 날짜 클래스

LocalDateTime
자바 8 의 새로운 기능 중 하나 로 날짜 클래스 가 추 가 됩 니 다.
프로젝트 개발 과정 에서 시간 처 리 를 자주 하 는데 정말 잘 사용 하 셨 나 요?알 리 바 바 개발 매 뉴 얼 에서 static 수식 Simple DateFormat 을 사용 하지 않 는 것 을 이해 하 십 니까?
이 글 을 읽 으 면 다음 과 같은 것 을 알 게 될 것 이다.
  • 왜 LocalDate,LocalTime,LocalDateTime[java 8 에서 새로 제공 한 클래스]
  • 자바 8 의 새로운 시간 API 사용 방식 은 생 성,포맷,해석,계산,수정
  • 을 포함한다.
    Date 대신 Instant,Calendar 대신 LocalDateTime,SimpleDateFormatter 대신 DateFormatter 를 사용 할 수 있 습 니 다.
    SimpleDateFormat 스 레 드 가 안전 하지 않 습 니 다.
    Date 를 포맷 하지 않 으 면 인쇄 된 날짜 의 가 독성 이 떨 어 집 니 다.
    
    Tue Sep 10 09:34:04 CST 2019
    Simple DateFormat 을 사용 하여 시간 을 포맷 하지만 Simple DateFormat 은 스 레 드 가 안전 하지 않 은 Simple DateFormat 의 format 방법 으로 원본 코드 를 최종 호출 합 니 다.
    
    private StringBuffer format(Date date, StringBuffer toAppendTo,
                                  FieldDelegate delegate) {
            // Convert input date to time field list
            calendar.setTime(date);
     
            boolean useDateFormatSymbols = useDateFormatSymbols();
     
            for (int i = 0; i < compiledPattern.length; ) {
                int tag = compiledPattern[i] >>> 8;
                int count = compiledPattern[i++] & 0xff;
                if (count == 255) {
                    count = compiledPattern[i++] << 16;
                    count |= compiledPattern[i++];
                }
     
                switch (tag) {
                case TAG_QUOTE_ASCII_CHAR:
                    toAppendTo.append((char)count);
                    break;
     
                case TAG_QUOTE_CHARS:
                    toAppendTo.append(compiledPattern, i, count);
                    i += count;
                    break;
     
                default:
                    subFormat(tag, count, delegate, toAppendTo, useDateFormatSymbols);
                    break;
                }
            }
            return toAppendTo;
        }
    
    주의calendar.setTime(date);,Calendar 류 는 기본적으로 final 로 장식 되 어 있 으 며,calendar 는 공유 변수 이 며,이 공유 변 수 는 라인 보안 제 어 를 하지 않 았 습 니 다.여러 스 레 드 가 같은 Simple DateFormat 대상 을 동시에 사용 할 때[예 를 들 어 static 로 장 식 된 Simple DateFormat 은 보통 도구 류 에 패키지 되 어 재 활용]format 방법 을 호출 할 때 여러 스 레 드 가 calendar.setTime 방법 을 동시에 호출 합 니 다.한 스 레 드 가 time 값 을 설정 한 지 다른 스 레 드 가 설정 한 time 값 을 바로 수정 하여 되 돌아 오 는 포맷 시간 이 잘못 되 었 을 수 있 습 니 다.
    다 중 동시 다발 상황 에서 Simple DateFormat 을 사용 하려 면 특히 주의해 야 합 니 다.
    Simple DateFormat 은 format 방법 이 스 레 드 가 안전 하지 않 은 것 을 제외 하고 parse 방법 도 스 레 드 가 안전 하지 않 습 니 다.parse 방법 은 실제 적 으로 alb.estable(calendar).getTime()방법 을 호출 하여 분 석 했 습 니 다.alb.estable(calendar)방법 은 주로 완성 되 었 습 니 다.
  • 날짜 대상 cal 의 속성 값 초기 화
  • calb(calBuilder)중 속성 설정 cal
  • 사용 하기
  • 설 치 된 cal 대상 을 되 돌려 줍 니 다
  • 하지만 이 세 단 계 는 원자 조작 이 아니다.
    SimpleDateFormat 스 레 드 안전 을 어떻게 보장 합 니까?
  • 스 레 드 간 에 Simple DateFormat 대상 을 공유 하지 않도록 합 니 다.스 레 드 마다 Simple DateFormat 대상 을 만 듭 니 다=>대상 을 만 들 고 없 애 는 비용 이 많이 듭 니 다
  • format 와 parse 방법 을 사용 하 는 곳 에 자 물 쇠 를 추가 합 니 다=>스 레 드 차단 성능 이 떨 어 집 니 다
  • ThreadLocal 을 사용 하여 스 레 드 당 최대 한 번 만 Simple DateFormat 대상 을 만 들 수 있 도록 합 니 다=>좋 은 방법
  • Date 는 시간 처리 가 번 거 롭 습 니 다.예 를 들 어 특정한 해,특정한 달,특정한 주,그리고 n 일 이후 의 시간 을 얻 으 려 면 Date 로 처리 하 는 것 이 너무 어렵 습 니 다.Date 류 는 getYear,getMonth 등 방법 이 있 지 않 습 니까?연월일 을 얻 는 것 은 쉬 우 나 모두 버 려 졌 습 니 다.
    자바 8 새로운 날짜 와 시간 API
    자바 프로그램 을 사용 하여 데이터 베 이 스 를 조작 할 때,우 리 는 데이터베이스 형식 과 자바 형식 을 매 핑 해 야 한다.다음 표 는 데이터베이스 형식 과 자바 신 구 API 의 매 핑 관계 입 니 다.
    데이터베이스
    대응 하 는 자바 클래스(구)
    대응 하 는 자바 클래스(신규)
    DATETIME
    java.util.Date
    LocalDateTime
    DATE  
    java.sql.Date
    LocalDate
    TIME 
    java.sql.Time 
    LocalTime
    TIMESTAMP 
    java.sql.Timestamp 
    LocalDateTime
    LocalDate
    년 월 일 만 얻 을 수 있 습 니 다.
    
    //       
            LocalDate localDate = LocalDate.now();
            //        
            LocalDate localDate1 = LocalDate.of(2019, 9, 10);
    
            //   、 、 、   
            int year = localDate.getYear();
            int year1 = localDate.get(ChronoField.YEAR);
            Month month = localDate.getMonth();
            int month1 = localDate.get(ChronoField.MONTH_OF_YEAR);
            int day = localDate.getDayOfMonth();
            int day1 = localDate.get(ChronoField.DAY_OF_MONTH);
            DayOfWeek dayOfWeek = localDate.getDayOfWeek();
            int dayOfWeek1 = localDate.get(ChronoField.DAY_OF_WEEK);
    
    LocalTime
    몇 시 몇 분 몇 초 밖 에 못 받 아 요.
    
    //  LocalTime
            LocalTime localTime = LocalTime.of(13, 51, 10);
            LocalTime localTime1 = LocalTime.now();
    
            //    
            int hour = localTime.getHour();
            int hour1 = localTime.get(ChronoField.HOUR_OF_DAY);
            //   
            int minute = localTime.getMinute();
            int minute1 = localTime.get(ChronoField.MINUTE_OF_HOUR);
            //   
            int second = localTime.getSecond();
            int second1 = localTime.get(ChronoField.SECOND_OF_MINUTE);
    
    LocalDateTime
    년 월 일 분 초 를 가 져 오 는 것 은 LocalDate+LocalTime 과 같 습 니 다.
    
    //    
            LocalDateTime localDateTime = LocalDateTime.now();
            LocalDateTime localDateTime1 = LocalDateTime.of(2019, Month.SEPTEMBER, 10, 14, 46, 56);
            //LocalDate+LocalTime-->LocalDateTime
            LocalDateTime localDateTime2 = LocalDateTime.of(localDate, localTime);
            LocalDateTime localDateTime3 = localDate.atTime(localTime);
            LocalDateTime localDateTime4 = localTime.atDate(localDate);
    
            //  LocalDate
            LocalDate localDate2 = localDateTime.toLocalDate();
            //  LocalTime
            LocalTime localTime2 = localDateTime.toLocalTime();
    
    ZonedDateTimeLocalDateTime항상 현지 날짜 와 시간 을 표시 하고 시간 대 를 가 진 날짜 와 시간 을 표시 하려 면 우 리 는ZonedDateTime이 필요 하 다.
    간단하게ZonedDateTimeLocalDateTime더하기ZoneId로 이해 할 수 있다.ZoneIdjava.time도 입 된 새로운 시간 대 유형 으로 주의 와 낡은java.util.TimeZone의 차이 점 이다.
    대상 만 들 기ZonedDateTime
    
    //     
    ZonedDateTime zbj = ZonedDateTime.now(); 
    //            
    ZonedDateTime zny = ZonedDateTime.now(ZoneId.of("America/New_York")); 
    결과:
    2019-09-15T20:58:18.786182+08:00[Asia/Shanghai]
    2019-09-15T08:58:18.788860-04:00[America/New_York]
    다른 생 성 방식 은 하나LocalDateTime에 하나ZoneId를 추가 하면ZonedDateTime로 변 할 수 있 습 니 다.
    
    LocalDateTime ldt = LocalDateTime.of(2019, 9, 15, 15, 16, 17);
    ZonedDateTime zbj = ldt.atZone(ZoneId.systemDefault());
    ZonedDateTime zny = ldt.atZone(ZoneId.of("America/New_York"));
    
    시간 대 전환
    시간 대 를 바 꾸 려 면 먼저 하나의ZonedDateTime대상 이 필요 하 다.그 다음 에withZoneSameInstant()을 통 해 관련 시간 대 를 다른 시간 대 로 바 꾸 고 전환 한 후에 날짜 와 시간 은 상응 하 게 조정 된다.
    
    ZonedDateTime zbj = ZonedDateTime.now(ZoneId.of("Asia/Shanghai"));
    //        :
    ZonedDateTime zny = zbj.withZoneSameInstant(ZoneId.of("America/New_York"));
    
    ZonedDateTime여전히plusDays()등 가감 조작 을 제공 했다.
    특히 시간 대가 바 뀔 때 여름 캠프 가 존재 하기 때문에 날짜 가 다 를 수 있 으 므 로 주의해 야 한다.이것 은 베 이 징 시간 9 월 15 일의 전환 결과 이다.
    2019-09-15T21:05:50.187697+08:00[Asia/Shanghai]
    2019-09-15T09:05:50.187697-04:00[America/New_York]
    이것 은 베 이 징 시간 11 월 15 일의 전환 결과 이다.
    2019-11-15T21:05:50.187697+08:00[Asia/Shanghai]
    2019-11-15T08:05:50.187697-05:00[America/New_York]
    두 차례 전 환 된 뉴욕 시간 은 1 시간의 여름 시차 가 있다.시간 대 에 관련 되 었 을 때 는 절대 스스로 시 차 를 계산 하지 마라.그렇지 않 으 면 여름 캠프 를 정확하게 처리 하기 어렵다.ZonedDateTime이 있 으 면 이 를 현지 시간 으로 바 꾸 는 것 이 매우 간단 하 다.
    
    ZonedDateTime zdt = ...
    LocalDateTime ldt = zdt.toLocalDateTime();
    LocalDateTime로 전환 할 때 시간 대 정 보 를 직접 버 렸 다.
    Instant
    초 또는 시간 스탬프 가 져 오기
    
    //  Instant  
            Instant instant = Instant.now();
            //    
            long currentSecond = instant.getEpochSecond();
            //     
            long currentMilli = instant.toEpochMilli();
            long l = System.currentTimeMillis();
    
    System.currentTimeMillis()도 밀리초 수 를 얻 을 수 있 습 니 다.
    날짜 계산
    LocalDate,LocalTime,LocalDateTime,Instant 는 가 변 대상 이 며,이 대상 을 수정 하면 복사 본 을 되 돌려 줍 니 다.
    연수,월 수,일수 등 을 증 가·감소 하고,LocalDateTime 의 경우
    
    //  LocalDate、LocalTime、LocalDateTime、Instant
            LocalDateTime localDateTime = LocalDateTime.of(2019, Month.SEPTEMBER, 10,
                    14, 46, 56);
            //    
            localDateTime = localDateTime.plusYears(1);
            localDateTime = localDateTime.plus(1, ChronoUnit.YEARS);
            //     
            localDateTime = localDateTime.minusMonths(1);
            localDateTime = localDateTime.minus(1, ChronoUnit.MONTHS);
    
    		//  with     
            //    2020
            localDateTime = localDateTime.withYear(2020);
            //   2022
            localDateTime = localDateTime.with(ChronoField.YEAR, 2022);
    		//      、 
    
    이 달의 마지막 날 이 며칠 인지,다음 주말 이 며칠 인지 궁금 할 때 가 있 는데 제 공 된 시간 과 날짜 API 를 통 해 빠르게 답 을 얻 을 수 있 습 니 다.
    
    LocalDate localDate = LocalDate.now();
    LocalDate localDate1 = localDate.with(TemporalAdjusters.firstDayOfYear());
    예 를 들 어 firstDayOfYear()를 통 해 현재 년 의 첫날 날 짜 를 되 돌 렸 고 많은 방법 이 있 습 니 다.여기 서 예 를 들 어 설명 하지 않 습 니 다.
    포맷 시간
    DateTimeFormatter 는 기본적으로 다양한 포맷 방식 을 제공 합 니 다.기본 값 으로 요 구 를 만족 시 키 지 못 하면 DateTimeFormatter 의 ofPattern 방법 으로 사용자 정의 포맷 방식 을 만 들 수 있 습 니 다.
    
    LocalDate localDate = LocalDate.of(2019, 9, 10);
    String s1 = localDate.format(DateTimeFormatter.BASIC_ISO_DATE);
    String s2 = localDate.format(DateTimeFormatter.ISO_LOCAL_DATE);
    //      
    DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
    String s3 = localDate.format(dateTimeFormatter);
    
    해석 시간
    Simple DateFormat 에 비해 DateTimeFormatter 는 스 레 드 가 안전 합 니 다.
    
    LocalDate localDate1 = LocalDate.parse("20190910", DateTimeFormatter.BASIC_ISO_DATE);
    LocalDate localDate2 = LocalDate.parse("2019-09-10", DateTimeFormatter.ISO_LOCAL_DATE);
    
    SimpleDateFormat 대신 DateTimeFormatter
    오래된Date대상 을 사용 할 때,우 리 는SimpleDateFormat으로 포맷 하여 표시 합 니 다.새로운LocalDateTime또는ZonedLocalDateTime을 사용 할 때 포맷 디 스 플레이 를 하려 면DateTimeFormatter을 사용 해 야 합 니 다.SimpleDateFormat와 달리DateTimeFormatter변 하지 않 는 대상 일 뿐만 아니 라 스 레 드 가 안전 하 다.SimpleDateFormat스 레 드 가 안전 하지 않 기 때문에 사용 할 때 방법 내부 에 새로운 부분 변 수 를 만 들 수 밖 에 없습니다.DateTimeFormatter인 스 턴 스 만 만 들 고 여기저기 서 참조 할 수 있 습 니 다.
    
    //   1:       
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    
    //   2:          
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("E, yyyy-MMMM-dd HH:mm:ss", Locale.US);
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("E, yyyy-MMMM-dd HH:mm:ss", Locale.CHINA);
    
    DateTimeFormatter 바 텀 원리
    DateTimeFormatter 스 레 드 가 안전 합 니까?왜?
    원본 코드:
    在这里插入图片描述
    분명 한 것 은 final 수식 류 를 통 해 계승 할 수 없고 final 수식 변 수 는 가 변 류 를 만 들 었 습 니 다.String 과 유사 하여 스 레 드 가 안전 할 뿐만 아니 라 효율 적 입 니 다.전역 적 으로 하나의 대상 만 있 고 여러 스 레 드 가 참조 할 수 있 습 니 다.
    format 와 parse 스 레 드 보안 대체
    LocalDateTime 의 format 와 parse 방법 을 사용 하여 대응 하 는 DateTimeFormatter 대상 인 자 를 입력 합 니 다.실제 적 으로 DateTimeFormatter 의 format 와 parse 방법 을 호출 하여 날짜 포맷 과 해석 을 실현 하 는 것 이 안전 합 니 다.
    DateTimeFormatter 클래스 는 LocalDateTime 의 날짜 변 수 를 해석 하여 StringBuilder 로 되 돌려 줍 니 다.LocalDateTime 등 새로 나 온 날짜 클래스 는 모두 final 수식 클래스 로 계승 할 수 없 으 며,대응 하 는 날짜 변 수 는 모두 final 수식 클래스,즉 가 변 클래스 입 니 다.값 을 한 번 부여 한 후 에는 가 변 적 이지 않 고 다 중 스 레 드 데이터 문제 가 존재 하지 않 습 니 다.
    在这里插入图片描述
    자바 8 의 새로운 특성 에 관 한 스 레 드 보안 날짜 류 에 관 한 글 은 여기까지 소개 되 었 습 니 다.자바 8 스 레 드 보안 날짜 류 에 관 한 내용 은 예전 의 글 을 검색 하거나 아래 의 관련 글 을 계속 찾 아 보 세 요.앞으로 저 희 를 많이 사랑 해 주세요!

    좋은 웹페이지 즐겨찾기