찾다

 >  Q&A  >  본문

Java SImpleDateFormat线程安全问题

public class Test {
    private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

    private static class Task implements Runnable {

        public void run() {
            try {
                System.out.println(sdf.parse("2016-03-21 12:00:00").getTime());
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        Task task = new Task();

        Thread t1 = new Thread(task);
        t1.start();
        Thread t2 = new Thread(task);
        t2.start();
        Thread t3 = new Thread(task);
        t3.start();
        Thread t4 = new Thread(task);
        t4.start();
        Thread t5 = new Thread(task);
        t5.start();
    }
}

最近才知道,如果像上面代码那样通过定义静态共享的实例来使用SimpleDateFormat是会存在线程安全问题的。

例如线程被挂死:

或者转换的时间不对:

然后自己尝试读JDK源码来试图分析在SimpleDateFormat的代码中,究竟是哪里的函数或者代码会引起线程不安全,但是由于水平有限,最后还是找不出。

哪位大牛可以帮忙分析一下。

PS:我的jdk版本:1.8.0_73

PHP中文网PHP中文网2810일 전521

모든 응답(3)나는 대답할 것이다

  • ringa_lee

    ringa_lee2017-04-17 17:33:32

    parse() 소스코드의 주석을 살펴보니 이 사람이 쓴 부분이 있습니다

    이 구문 분석 작업에서는 {@link DateFormat#calendar

    를 사용합니다.
    • calendar}를 사용하여 모든 {@code

    • 를 생성합니다.
    • calendar}의 날짜-시간 필드는 {@linkplain Calendar#clear()

    • 입니다. 파싱하기 전에
    • cleared}, {@code Calendar}의 기본값

    • 누락된 항목에는 날짜-시간 필드의 값이 사용됩니다

    • 날짜-시간 정보

    일반적인 의미는 pars() 메서드가 반환된 Date 인스턴스를 생성하기 위해 달력을 사용한다는 것입니다. 문제는 여기서 사용하는 달력이 메서드가 실행될 때마다 새로운 달력이 아니라는 것입니다. " 속성입니다. 주석의 의미에 따라 각 구문 분석 전에 달력의 관련 속성이 지워지고 객체가 새로운 처리 결과로 채워집니다. 이 경우 멀티 스레드에서는 실행 중에 parse(), 달력을 설정한 후 다른 스레드가 이를 지웠습니다. sdf 인스턴스이기 때문에 이로 인해 다른 문제가 발생해야 합니다.

    회신하다
    0
  • PHP中文网

    PHP中文网2017-04-17 17:33:32

    으아아아

    여기에 사용된 달력은 클래스 멤버이며 멀티스레딩 setTime은 스레드 안전 문제를 일으킬 것입니다

    회신하다
    0
  • 伊谢尔伦

    伊谢尔伦2017-04-17 17:33:32

    이것은 SimpleDateFormat의 구현과 아무 관련이 없습니다. 여러 스레드에서 동일한 개체를 사용하고 스레드를 동기화하지 못하는 것과 관련이 있습니다

    회신하다
    0
  • 취소회신하다