5

Powyższe oświadczenie jest wymienione w javadoc SwingWorker.Dlaczego komponenty Swing powinny być dostępne tylko w wątku wysyłki zdarzeń?

W aplikacji Widziałem czasochłonne zadanie tła działa w odrębnym wątku UI i aktualizuje również bez problemu (odniesienie do składnika Swing był dostępny).

Czy może się zdarzyć coś złego?

+2

* "Czy może się zdarzyć coś złego?" * - Tak. Mówiąc krótko, Swing nie jest bezpieczny dla wątków, nie chroni przed dostępem wielu wątków do różnych właściwości, co może oznaczać, że staniesz się niespójny. Pamiętaj, że nie kontrolujesz procesu malowania, więc coś może się malować, gdy zmieniasz to ... te problemy są trudne do powielenia i śledzenia, a co gorsza, wydają się zdarzać tylko na komputerach użytkowników .. .. – MadProgrammer

+0

Nie oszukujmy się, to jest naprawdę, naprawdę niebezpieczny i naprawdę, naprawdę zły pomysł – MadProgrammer

+0

1. dlaczego, 2. moja ciekawość jest naprawdę powodem, by zadać pytanie na temat, 3. zauważ, że jest ogromna różnica w bezpieczeństwie Nici pomiędzy Java6 i Java7/8, 4. głosowanie na zakończenie jako zbyt szerokie (bez SSCCE/MCVE, krótkie, działające, kompilowalne, z zakodowaną wartością dla Swing GUI w zmiennej lokalnej) – mKorbel

Odpowiedz

6

To dlatego, że Java memory model nie gwarantuje, że zapisy w pamięci przez jeden wątek będą widoczne dla innych wątków, chyba że użyjesz jakiejś formy synchronizacji. Dla wydajności i prostoty Swing nie jest zsynchronizowany. Dlatego też zapisy z innych wątków mogą nigdy nie być widoczne dla EDT.

Aplikacja widzieliście może pracować przez większość czasu, a może nawet pracować cały czas w niektórych środowiskach. Ale kiedy to nie zadziała, zawodzi w naprawdę dziwnych drogach, które są trudne do odtworzenia.

+0

[tutaj] (https://weblogs.java.net/blog/kgh/archive/2004/10/multithreaded_t.html) argument o tym, dlaczego Swing * ma * być singlethreaded. "Dla uproszczenia" sprawia, że ​​brzmi to jak projekt leniwości lub wada. – DSquare

+0

@DSquare Świetna lektura i myślę, że dotyczy to więcej niż tylko zestawów narzędzi interfejsu użytkownika. Wiele wielowątkowych programów można znacznie uprościć za pomocą jednowątkowego podejścia do kolejki zdarzeń. A jeśli chodzi o oprogramowanie, powiedziałbym, że "prostota" ma silnie pozytywne konotacje. :) –

5

Wszystkie składniki piłowania są realizowane być dostępne z jednej nici (dla wątku zdarzenie wysyłki). Tak więc nie ma żadnych zabezpieczeń przeciwko współbieżnemu dostępowi i jednoczesnym zmianom zmiennych i pola.

Jeśli masz szczęście, wszystko działa dobrze. Ale nie można na nim polegać, a ten sam kod może mieć ogromne problemy przy następnym uruchomieniu.

Prosty przykład:

Procedura farby z JLabel zawiera następujące (uproszczony) kod (wzięte z BasicLabelUI klasa):

# 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); 
    } 

Na przykład jeśli zadzwonisz setEnabled() z innych wątków niż EDT byłoby możliwe, że otrzymasz etykietę z włączoną ikoną, ale wyłączony tekst malowany.

Powiązane problemy