Java SImpleDateFormat线程安全问题
PHP中文网
PHP中文网 2017-04-17 17:31:32
0
3
518
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中文网

认证高级PHP讲师

répondre à tous(3)
左手右手慢动作

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

.
Ty80
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

伊谢尔伦

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

Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal