5

Die obige Aussage wird im SwingWorker Javadoc erwähnt.Warum sollten Swing-Komponenten nur im Event-Dispatch-Thread aufgerufen werden?

In einer Anwendung habe ich gesehen, eine lange Hintergrundaufgabe in einem bestimmten Thread ausgeführt und aktualisiert die Benutzeroberfläche auch ohne ein Problem (ein Verweis auf eine Swing-Komponente war zugänglich).

Könnte es sein, dass etwas Schlimmes passieren kann?

+2

* "Könnte es sein, dass etwas Schlimmes passieren kann?" * - Ja. Einfach ausgedrückt ist Swing nicht Thread-sicher, es schützt nicht vor dem Zugriff mehrerer Threads auf verschiedene Eigenschaften, was dazu führen kann, dass Sie in einen inkonsistenten Zustand geraten. Denken Sie daran, dass Sie den Malprozess nicht kontrollieren, also könnte etwas beim Malen malen, während Sie es ändern ... diese Probleme sind schwer zu replizieren und aufzuspüren und das Schlimme ist, dass sie nur auf den Computern Ihrer Benutzer passieren. .. – MadProgrammer

+0

Mach dir nichts vor, das ist wirklich, wirklich gefährlich und eine wirklich, sehr schlechte Idee – MadProgrammer

+0

1. warum, 2. meine Neugier wirklich Grund, eine Frage zu stellen, 3. beachten Sie, es gibt einen großen Unterschied in der Threadsicherheit zwischen Java6 und Java7/8, 4. voting zu schließen als zu breit (ohne SSCCE/MCVE, kurz, lauffähig, kompilierbar, mit festem Wert für Swing GUI in lokaler Variable) – mKorbel

Antwort

6

Es ist, weil die Java memory model nicht garantiert, dass Arbeitsspeicher schreibt von einem Thread für andere Threads sichtbar ist, es sei denn, Sie verwenden irgendeine Form der Synchronisierung. Für Leistung und Einfachheit ist Swing nicht synchronisiert. Daher können Schreibvorgänge von anderen Threads für die EDT möglicherweise nie sichtbar sein.

Die Anwendung, die Sie gesehen haben, funktioniert möglicherweise die meiste Zeit, und es kann sogar die ganze Zeit in einigen Umgebungen funktionieren. Aber wenn es nicht funktioniert, wird es auf wirklich seltsame Weise scheitern, die schwer zu reproduzieren sind.

+0

[Hier ist] (https://weblogs.java.net/blog/kgh/archive/2004/10/multithreaded_t.html) ein Argument darüber, warum Swing * Singlethreading * sein muss. "Aus Gründen der Einfachheit" lässt es wie Designfaulheit oder einen Fehler klingen. – DSquare

+0

@DSquare Großartig gelesen, und ich denke, das gilt für mehr als nur UI-Toolkits. Viele Multithread-Programme könnten durch einen single-threaded Ereignisqueue-Ansatz stark vereinfacht werden. Und wenn es um Software geht, würde ich sagen "Einfachheit" hat eine stark positive Konnotation. :) –

5

Alle Swing-Komponenten sind so implementiert, dass sie von einem einzelnen Thread (dem Event-Dispatching-Thread) aus aufgerufen werden können. Es gibt also keinen Schutz gegen gleichzeitigen Zugriff und gleichzeitige Änderungen von Variablen und Feldern.

Wenn Sie Glück haben, funktioniert alles gut. Aber Sie können sich nicht darauf verlassen, und derselbe Code kann beim nächsten Lauf massive Probleme verursachen.

Ein einfaches Beispiel:

Die Farbe Prozedur eines JLabel enthält folgende (vereinfachte) Code (von BasicLabelUI Klasse übernommen):

# assume your label is enabled 
    Icon icon = (label.isEnabled()) ? label.getIcon() : label.getDisabledIcon(); 

    # what happens if another thread calls label.setEnabled(false) at this point? 

    if (icon != null) { 
     icon.paintIcon(c, g, paintIconR.x, paintIconR.y); 
    } 

    if (label.isEnabled()) { 
     paintEnabledText(label, g, clippedText, textX, textY); 
    } 
    else { 
     paintDisabledText(label, g, clippedText, textX, textY); 
    } 

Zum Beispiel, wenn Sie von anderen Threads setEnabled() aufrufen als die EDT wäre es möglich, dass Sie eine Beschriftung mit dem aktivierten Symbol erhalten, aber den deaktivierten, gemalten Text.

Verwandte Themen