recherche

Maison  >  Questions et réponses  >  le corps du texte

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 Il y a quelques jours522

répondre à tous(3)je répondrai

  • ringa_lee

    ringa_lee2017-04-17 17:33:32

    J'ai jeté un œil aux commentaires du code source de parse(), et il y a une section écrite par cette personne

    Cette opération d'analyse utilise le {@link DateFormat#calendar

    • calendrier} pour produire une {@code Date} Tous les {@code

    • . Les champs date-heure de
    • calendar} sont {@linkplain Calendar#clear()

    • effacé} avant l'analyse, et la valeur par défaut du {@code calendrier}

    • les valeurs des champs date-heure sont utilisées pour tout élément manquant

    • informations date-heure.

    La signification générale est que la méthode parse() utilise le calendrier pour générer l'instance Date renvoyée. Le problème est que le calendrier qu'elle utilise ici n'est pas nouveau à chaque fois que la méthode est exécutée. Elle définit un "Calendrier protégé". "calendrier", selon la signification du commentaire, avant chaque analyse, tous les attributs pertinents du calendrier seront effacés, puis l'objet sera rempli avec de nouveaux résultats de traitement. Dans ce cas, en multi-threads, lors de l'exécution de parse(), ce sera le cas. Après qu'un thread vient de définir le calendrier, un autre thread l'efface. Comme il s'agit d'une instance sdf, d'autres problèmes devraient être causés par cela

    .

    répondre
    0
  • PHP中文网

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

    private StringBuffer format(Date date, StringBuffer toAppendTo,
                                    FieldDelegate delegate) {
            // Convert input date to time field list
            calendar.setTime(date);
    
            boolean useDateFormatSymbols = useDateFormatSymbols();
            
            ...
     }  
    
    

    Le calendrier utilisé ici est un membre de classe, et setTime multithread entraînera des problèmes de sécurité des threads

    répondre
    0
  • 伊谢尔伦

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

    Cela n'a rien à voir avec l'implémentation de SimpleDateFormat. Cela a à voir avec le fait que vous utilisez le même objet dans plusieurs threads et que vous ne parvenez pas à synchroniser les threads

    répondre
    0
  • Annulerrépondre