Frage

Die javadoc für Simple besagt, dass Simple nicht synchronisiert ist.

  Es

"Datumsformate werden nicht synchronisiert.   wird empfohlen, getrennt zu erstellen   Format-Instanzen für jeden Thread. Wenn   mehrere Threads zugreifen ein Format   Gleichzeitig muss sie synchronisiert werden   nach außen. "

Aber was ist der beste Ansatz ist eine Instanz von Simple in einer multi-threaded Umgebung zu verwenden. Hier sind ein paar Optionen, die ich gedacht habe von, ich habe verwendet Optionen 1 und 2 in der Vergangenheit, aber ich bin neugierig, ob es bessere Alternativen gibt oder welche dieser Optionen wäre die beste Leistung und Parallelität bieten.

Option 1: lokale Instanzen erstellen bei Bedarf

public String formatDate(Date d) {
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    return sdf.format(d);
}

Option. 2: Erstellen Sie eine Instanz von Simple als Klassenvariable aber synchronisieren Zugriff auf sie

private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
public String formatDate(Date d) {
    synchronized(sdf) {
        return sdf.format(d);
    }
}

Option 3: a. Thread erstellen für jeden Thread eine andere Instanz von Simple speichern

private ThreadLocal<SimpleDateFormat> tl = new ThreadLocal<SimpleDateFormat>();
public String formatDate(Date d) {
    SimpleDateFormat sdf = tl.get();
    if(sdf == null) {
        sdf = new SimpleDateFormat("yyyy-MM-hh");
        tl.set(sdf);
    }
    return sdf.format(d);
}

Andere Tipps

Die andere Option ist Commons Lang FastDateParser , das ein Drop-in-threadsicher Ersatz für Simple)

Wenn Sie mit Java 8, können Sie verwenden möchten < strong> java.time.format.DateTimeFormatter :

  

Diese Klasse ist unveränderlich und Thread-sicher.

z.

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
String str = new java.util.Date().toInstant()
                                 .atZone(ZoneId.systemDefault())
                                 .format(formatter);

Commons Lang 3.x hat jetzt FastDateParser sowie FastDateFormat. Es ist Thread-sicher und schneller als Simple. Es verwendet auch die gleiche Format / Parse-Muster Spezifikationen wie Simple.

Verwenden Sie Simple nicht, verwenden joda Zeit des DateTimeFormatter statt. Es ist ein wenig strenger in der Parsing-Seite und so ist nicht ganz ein direkter Ersatz für Simple, aber joda-Zeit ist viel mehr gleichzeitige freundlich in Bezug auf Sicherheit und Leistung.

Ich würde sagen, erstellen Sie eine einfache Wrapper-Klasse für Simple, den Zugriff auf Parse synchronisiert () und Format () und kann als Drop-in-Ersatz verwendet werden. Mehr als narrensicher Ihre Option # 2, weniger umständlich als Ihre Option # 3.

Es scheint, wie das Bilden Simple unsynchronisierten ein schlechtes Design Entscheidung über den Teil der Java-API-Designer war; Ich bezweifle, jemand erwartet Format () und parse () nach Bedarf synchronisiert werden.

Eine andere Möglichkeit ist Instanzen in einer Thread-sichere Warteschlange zu halten:

import java.util.concurrent.ArrayBlockingQueue;
private static final int DATE_FORMAT_QUEUE_LEN = 4;
private static final String DATE_PATTERN = "yyyy-MM-dd HH:mm:ss";
private ArrayBlockingQueue<SimpleDateFormat> dateFormatQueue = new ArrayBlockingQueue<SimpleDateFormat>(DATE_FORMAT_QUEUE_LEN);
// thread-safe date time formatting
public String format(Date date) {
    SimpleDateFormat fmt = dateFormatQueue.poll();
    if (fmt == null) {
        fmt = new SimpleDateFormat(DATE_PATTERN);
    }
    String text = fmt.format(date);
    dateFormatQueue.offer(fmt);
    return text;
}
public Date parse(String text) throws ParseException {
    SimpleDateFormat fmt = dateFormatQueue.poll();
    if (fmt == null) {
        fmt = new SimpleDateFormat(DATE_PATTERN);
    }
    Date date = null;
    try {
        date = fmt.parse(text);
    } finally {
        dateFormatQueue.offer(fmt);
    }
    return date;
}

Die Größe der dateFormatQueue sollte etwas in der Nähe der geschätzten Anzahl von Threads sein, die routinemäßig diese Funktion zur gleichen Zeit aufrufen können. Im schlimmsten Fall, wenn mehr Threads als diese Zahl haben tatsächlich alle gleichzeitig Instanzen verwenden, werden einige Simple Instanzen erstellt werden, die nicht zu dateFormatQueue zurückgeführt werden kann, weil es voll ist. Dies wird nicht zu einem Fehler, es wird nur die Strafe für die Schaffung einiger Simple entstehen, die nur einmal verwendet werden.

I umgesetzt dies nur mit Option 3, machte aber ein paar Änderungen am Code:

  • Thread sollte in der Regel statisch
  • sein
  • Scheint Reiniger außer Kraft zu setzen Anfangswert () und nicht Test if (get () == null)
  • Sie können auf Gebietsschema und die Zeitzone wollen, wenn Sie wirklich die Standardeinstellungen möchten (Standardwerte sind sehr anfällig für Fehler mit Java)

    private static final ThreadLocal<SimpleDateFormat> tl = new ThreadLocal<SimpleDateFormat>() {
        @Override
        protected SimpleDateFormat initialValue() {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-hh", Locale.US);
            sdf.setTimeZone(TimeZone.getTimeZone("America/Los_Angeles"));
            return sdf;
        }
    };
    public String formatDate(Date d) {
        return tl.get().format(d);
    }
    

Stellen Sie sich Ihre Anwendung hat einen Thread. Warum würden Sie Zugriff auf Simple Variable synchronisieren dann?

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top