JProgressBar actionPerformedMethode und SwingUI thread

Status
Nicht offen für weitere Antworten.
G

Guest

Gast
Hallo,

ich wollte nach Button Klick in der actionPerformedMethode eine Fortschrittsanzeige mittels einer JProgressBar
realisieren.

in der Art:

actionPerformed() {

1. Fortschrittsanzeige (unbestimmte) erzeugen in Panel A
2. Methodenaufruf, der eine gewisse Zeit benötigt und Ergebnis B liefert
3. Fortschrittsanzeige aus Panel A entfernen und Ergebnis B hinzufügen

}

Nun habe ich mich gewundert, dass dies so nicht funktioniert, da ein neuzeichnen erst möglich ist, wenn mein actionPerformed beendet ist, wie ich hier: http://forums.sun.com/thread.jspa?threadID=427336&tstart=-2 lesen konnte.

Nun die Frage, wo bekomme ich nähere Infos zu diesem Swing UI thread, der mein Neuzeichnen blockiert? Und wieso isr das denn so gelöst (blockieren des neuzeichnens während der actionPerformed Methode)?
 

Ebenius

Top Contributor
Anonymous hat gesagt.:
Nun die Frage, wo bekomme ich nähere Infos zu diesem Swing UI thread, der mein Neuzeichnen blockiert? Und wieso isr das denn so gelöst (blockieren des neuzeichnens während der actionPerformed Methode)?
Dieser ominöse Swing UI thread ;-) ist der AWT Event Dispatcher Thread. Dieser Thread versendet alle Events im AWT / Swing. Sowohl die Events zum Zeichnen als auch die MouseEvents, KeyEvents, ActionEvents, etc.

Sun Article: Threads and Swing
 
G

Gast

Gast
Hallo nochmal,

habe den Fortschrittsbalken in einen eigenen Thread ausgelagert, aber auch da wird dieser nicht sofort angezeigt.

Pseudocode:

actionPerformed()
{

startProgressShowThread
// zeitintensive operation

}

Auch hier wird mein Balken nicht angezeigt, obwohl ich nen eigenen Thread hab der ein Fenster mit der ProgressBar erzeugt und diesen Thread noch vor der eigentlichen Operation mittels
"start()" aufrufe. Mein Thread prüft dann mittels eines flags, ob die operation durchgeführt werden konnte und beendet sich dann. Das klappt auch, wenn ich mir das mal mit sysout anschaue. Aber den Balken als solches bekomme ich nicht zu sehen
 

Ebenius

Top Contributor
Das ist halt genau verkehrt herum. actionPerformed() wird im Event Dispatch Thread ausgeführt. Der selbe Thread muss auch zeichnen. Wenn Du innerhalb von actionPerformed die zeitintensiven Operationen ausführst, wird während derer nicht gezeichnet. Kannst ja mal das Fenster verkleinern, während die Operation läuft, dann wirst Du sehen, dass auch dabei nicht gezeichnet wird, bis die Operation vorbei ist. Also: Nicht den ProgressShowThread erfinden, sondern die Operation auslagern; zum Beispiel unter Zuhilfenahme der SwingWorker-Klasse. Siehe dazu: Sun Article: Using a Swing Worker Thread.

Ebenius
 
G

Gast

Gast
Hallo Ebenius,

danke für die schnelle Antwort... Werde ich mir anschauen, aber wenn ein Buttonklick nunmal einen zeitintensive Operation auslösen soll? Wieso ist das so "blöd" gemacht in Java?
 

Ebenius

Top Contributor
Gast hat gesagt.:
[...] aber wenn ein Buttonklick nunmal einen zeitintensive Operation auslösen soll?
Steht doch oben. SwingWorker benutzen.

Gast hat gesagt.:
Wieso ist das so "blöd" gemacht in Java?
Bist Du sicher, dass Du den ersten Link auch gelesen hast?
Der Sun-Artikel hat gesagt.:
Why did we implement Swing this way?

There are several advantages in executing all of the user interface code in a single thread:
  • Component developers do not have to have an in-depth understanding of threads programming: Toolkits like ViewPoint and Trestle, in which all components must fully support multithreaded access, can be difficult to extend, particularly for developers who are not expert at threads programming. Many of the toolkits developed more recently, such as SubArctic and IFC, have designs similar to Swing's.
  • Events are dispatched in a predictable order: The runnable objects enqueued by invokeLater() are dispatched from the same event queue as mouse and keyboard events, timer events, and paint requests. In toolkits where components support multithreaded access, component changes are interleaved with event processing at the whim of the thread scheduler. This makes comprehensive testing difficult or impossible.
  • Less overhead: Toolkits that attempt to carefully lock critical sections can spend a substantial amount of time and space managing locks. Whenever the toolkit calls a method that might be implemented in client code (for example, any public or protected method in a public class), the toolkit must save its state and release all locks so that the client code can grab locks if necessary. When control returns from the method, the toolkit must regrab its locks and restore its state. All applications bear the cost of this, even though most applications do not require concurrent access to the GUI.

    Here's a description, written by the authors of the SubArctic Java Toolkit, of the problem of supporting multithreaded access in a toolkit:

    It is our basic belief that extreme caution is warranted when designing and building multi-threaded applications, particularly those which have a GUI component. Use of threads can be very deceptive. In many cases they appear to greatly simplify programming by allowing design in terms of simple autonomous entities focused on a single task. In fact in some cases they do simplify design and coding. However, in almost all cases they also make debugging, testing, and maintenance vastly more difficult and sometimes impossible. Neither the training, experience, or actual practices of most programmers, nor the tools we have to help us, are designed to cope with the non-determinism. For example, thorough testing (which is always difficult) becomes nearly impossible when bugs are timing dependent. This is particularly true in Java where one program can run on many different types of machines and OS platforms, and where each program must work under both preemptive or non-preemptive scheduling.

    As a result of these inherent difficulties, we urge you to think twice about using threads in cases where they are not absolutely necessary. However, in some cases threads are necessary (or are imposed by other software packages) and so subArctic provides a thread-safe access mechanism. This section describes this mechanism and how to use it to safely manipulate the interactor tree from an independent thread.
Ebenius
 
G

Gast

Gast
Hallo,

danke für die zahlreichen Antworten das hat mir schon weitergeholfen.

bisher war es so:

actionPerformed()
{

// Klasse K die mir zeitaufwändige Berechnung zur Verfügung stellt // und eine Liste zurückliefert

List list = K.calculate();

// in actionPerformed wird l aber erneut benötigt
doSomething(list)

}

Damit meine Fortschrittsanzeige funktioniert habe ich meinen Code nun wie folgt abgeändert

actionPerformed()
{
ProgressThread pt;
pt.start()

// in diesem wird in run nun die Methode aus K aufgerufen
CalculateThread {
run()
{
List list = K.calculate();
}
}



}


Aber noch immer folgendes Problem...

Mein Fortschritt wird angezeigt, jedoch fährt mein HauptProgramm natürlich fort mit
doSomething(List l)

wie kann ich es schaffen, dass mir der CalculateThread erst mein Ergebnis zurückliefert und ich dann auch wirklich Werte an doSomething übergeben kann?

Wenn ich den Debugger nutze, dann ist an der Stelle doSomething(List l) für die Liste l noch kein Wert aus dem Calculate Thread verfügbar.

Ich will also den Fortschrittsthread laufen lassen wie bisher, die Methode doSomething jedoch erst aufrufen, wenn mir der CalculateThread das (zeitaufwändig) berechnete Ergebnis zurückgeben konnte.

An der Stelle komme ich leider nicht mehr weiter. Ich habe bisher auch noch nichts grossartig mit Threads gemacht :-(
 
S

SlaterB

Gast
doSomething(List l)
gehört mit in den Thread, nicht in den ActionListener,

falls der Thread bisher eine eigene Klasse mit für sich abgeschlossenen System ist, dann definiere eine neue anonyme innere Thread-Klasse

new Thread() {
public void run() {
list =..
doSomething(list);
}
}.start();
}

quasi so wie man anonyme ActionListener definiert
 
G

Gast

Gast
Hallo nochmal,

generell kann ein Thread aber keine Ergebnisse ala return zurückliefern, oder? Ich müsste mir dann höchtens irgendwelche get Methoden schreiben, oder?

@Ebenius
Danke für das geduldige Antworten. Ich habe auch nochmal den Abschnitt "Why did we implement Swing this way?" gelesen, ihn aber trotzdem noch nicht ganz verstanden...

Ereignisbehandlung (wie beim Klick auf nen Button mittels actionPerformed) wird ja in einem eigenen Thread behandelt. Ich habe aber noch immer nicht verstanden wieso währenddessen kein "neuzeichnen" möglich ist und die GUI somit "still steht". Wäre prima, wenn du das nochmal kurz erklären könntest.
 
S

SlaterB

Gast
> Ich müsste mir dann höchtens irgendwelche get Methoden schreiben, oder?

korrekt
 

Ebenius

Top Contributor
Gast hat gesagt.:
Ereignisbehandlung (wie beim Klick auf nen Button mittels actionPerformed) wird ja in einem eigenen Thread behandelt. Ich habe aber noch immer nicht verstanden wieso währenddessen kein "neuzeichnen" möglich ist und die GUI somit "still steht". Wäre prima, wenn du das nochmal kurz erklären könntest.
Genau das ist es was Du falsch verstanden hast. Alle Event-Handlings (inkl. Zeichnen, actionPerformed, etc.) werden in dem selben Thread (Event Dispatch Thread) sequencell (EventQueue) abgearbeitet. Ist die actionPerformed()-Methode nicht fertig, warten alle anderen Events (auch Neuzeichnen) in der Queue.

Ebenius
 
G

Guest

Gast
Gast hat gesagt.:
danke für die schnelle Antwort... Werde ich mir anschauen, aber wenn ein Buttonklick nunmal einen zeitintensive Operation auslösen soll? Wieso ist das so "blöd" gemacht in Java?
Vielleicht, weil alle Betriebssysteme aus gutem Grund ein single-threaded UI Toolkit benutzen, und schon genug daran gescheitert sind ein multi-threaded Toolkit zu entwicheln, gar ein multi-threaded Toolkit für eine VM auf einem nativen single-threaded Toolkit aufzusetzen? Doofe Idee irgendwie? Selber blöd.
 
S

SlaterB

Gast
was gibts da zu scheitern? einfach new Thread {} und fertig,
man müsste beispielsweise nur die eine bestimmte ActionListener-Basisklasse vorgeben,
technisch ist das kein Problem, zumindest kann es der Programmierer ja durch eigene Threads erzwingen,

ob das auf Dauer gut ist und was inhaltlich dagegen spricht, das ist die Frage..
 

Ebenius

Top Contributor
SlaterB, es ging grad nur um die Frage, warum das Event Handling im AWT/Swing single-threaded ist... Nicht darum, dass man Funktionen nicht auch in Threads auslagern kann (was man natürlich u.U. tun muss). Oder habe ich Dich hier falsch verstanden?

[edit] Oder hast Du nur übersehen, dass Gast nicht gleich Gast war?

Ebenius
 
S

SlaterB

Gast
die Frage war
"Ich habe aber noch immer nicht verstanden wieso währenddessen kein "neuzeichnen" möglich ist und die GUI somit "still steht". "

deine technische Antwort 'weil es in einem Thread stattfindet' + zweiter Gast's Antwort 'mehrere Threads wär doch nicht so schön'
finde ich beide bisher am Thema vorbei,

ich verstehe die Frage so, wie ich sie beantwortet bzw. eher nur neuformuliert habe:
'warum ist nicht jede Aktion eines ActionListeners standardmäßig in einem neuen Thread?'

denn das hätte den Vorteil, dass die GUI nicht blockieren würde,
allerdings auch den Nachteil, dass man wohl GUI-Änderungen korrekterweise in SwingUtilities.invokeLater stecken müsste,
um auch mal eine Teilantwort zu geben
 

Ebenius

Top Contributor
Ah, so verstehe ich was Du meinst. Entschuldige, vielleicht stand ich einfach auf dem Schlauch. :)
 
G

Gast

Gast
Hallo,

danke an alle, insbesondere Ebenius...

>Genau das ist es was Du falsch verstanden hast.
>Alle Event-Handlings (inkl. Zeichnen, actionPerformed, etc.) >werden in dem selben Thread (Event Dispatch Thread) sequencell >(EventQueue) abgearbeitet. Ist die actionPerformed()-Methode >nicht fertig, warten alle anderen Events (auch Neuzeichnen) in der >Queue.

Aber wäre es nicht sinnvoller gewesen wenigstens das Zeichnen zuzulassen? Ich hab jetzt zwar das von dir (Ebenius) erläuterte Konzept funktionell verstanden aber noch nicht wieso auch das Zeichnen usw. in diesem Thread abgearbeitet werden, wenn doch damit die ganze GUI blockiert wird. Wäre prima, wenn du darauf nochmal eingehen könntest
 

Ebenius

Top Contributor
Beispiel 1: Du vergrößerst ein Fenster. Dein Fenstersystem (Windows, X, ...) schickt daraufhin eine Mitteilung an Deine Applikation (an das AWT Subsystem), dass das Fenster mit dem Handle XYZ seine Größe geändert hat. Danach schickt es üblicher Weise eine Mitteilung, dass das Fenster neu gezeichnet werden soll. Die Anwendung muss darauf reagieren, indem sie erst die Komponenten neu anordnet und dann die Komponenten neu zeichnet.

Beispiel 2: Du möchtest mit der Maus einen Button drücken. Dazu bewegst Du die Maus über den Button.Dein Fenstersystem sendet also an Deine Anwendung die Mitteilung, dass sich die Maus bewegt hat. Das AWT-Subsystem erkennt, dass die Maus sich in den Bereich des Buttons bewegt, sendet daraufhin eine Mitteilung (MOUSE_ENTERED) an den Button, dieser reagiert darauf, indem er einen anderen Rahmen (Rollover Border) bekommt und verlangt danach, dass er neu gezeichnet wird, damit Du den neuen Rahmen siehst. Danach drückst Du auf den Mausknopf. Die Anwendung bekommt vom Fenstersystem die Mitteilung, dass der Mausknopf gedrückt wird, das AWT-Subsystem erkennt, dass dies im Bereich des Buttons passiert, schickt wieder eine Mitteilung an den Button (MOUSE_PRESSED), der Button ändert seinen Status (PRESSED und ARMED), und verlangt dann, neu gezeichnet zu werden.

An beiden Beispielen kann man gut erkennen, dass jedwede Arten von Mitteilungen sinnvoller Weise sequenziell abgearbeitet werden sollten. Oft ergeben sich aus verschiedenen Mitteilungen Statusänderungen in Komponenten und dadurch die Notwendigkeit, diese Komponenten neu zu zeichnen. Beim Zeichnen wiederum müssen die Zustände der Komponenten abgefragt werden (ist der Knopf gedrückt → dunklerer Hintergrund und anderer Rahmen, hat das Textfeld Fokus → evtl. ein anderer Rahmen und ein Cursor, etc.). Das Zeichnen muss synchron zum Abarbeiten der Nachrichten passieren, damit der die Komponenten den richtigen Zustand zeichnen können. Ansonsten würden Probleme auftauchen, dass beispielsweise der Knopf schon den richtigen Rahmen hat, aber noch nicht die richtige Hintergrundfarbe.

Nachdem wir also festgestellt haben, dass sichergestellt sein muss, dass die Nachrichtenbearbeitung synchron zum Zeichnen passieren muss ─ das heißt, dass stets zwischen aber nie während bearbeiteten Nachrichten gezeichnet werden muss ─ ergibt sich die logische Konsequenz, dass beides im selben Thread stattfindet. Ansonsten müsste man zwei Threads benutzen (Event Dispatcher und Repaint Thread), diese aber gegeneinander synchronsieren, so dass stets der eine wartet während der andere etwas tut. Das wäre erstens aufwändiger, zweitens fehleranfälliger und hätte drittens noch immer das Problem zur Folge, dass nicht gezeichnet werden kann, während Nachrichten abgearbeitet werden.

Verstanden?
 
G

Gast

Gast
Hallo Ebenius,

danke für deine sehr ausführliche Erklärung. Ich versuche mal zusammenzufassen. Viele Events führen zu einer Statusänderung der Komponente welche mit einer visuellen Änderung der Komponente einhergeht. Das zeichnen sollte also nach der Abarbeitung des Events geschehen. Richtig?

OK, wenn aber mein Event nun aber nichts mit der GUI zu tun hat? Beispielsweise wenn der Buttonklick irgend eine Rechenoperation auslöst, die erstmal nichts mit einem grafischen Status zu tun hat könnte ich doch trotzdem z.B. einen Prozessfortschritt darstellen. Dies geht aber leider nicht, da ich ja solange ich in der Methode (actionPerformed) bin nix zeichnen kann, da das Zeichnen ja erst nach der Abarbeitung des Events erfolgt, was ja wie du mir anschaulich erläutern konntest für Events die GUI Änderungen auslösen auch völlig sinnvoll erscheint. Wieso kann ich aber nicht durch ein Schlüsselwort trotzdem auch inerhalb der Eventbehandlung ein Zeichnen anstoßen? Für den Fall des "wartens" in der Eventmethode, was keine GUI Änderung auslöst wäre das doch sinnvoll. Oder hab ich wieder was falsch verstanden?
 

Ebenius

Top Contributor
Gast hat gesagt.:
danke für deine sehr ausführliche Erklärung. Ich versuche mal zusammenzufassen. Viele Events führen zu einer Statusänderung der Komponente welche mit einer visuellen Änderung der Komponente einhergeht. Das zeichnen sollte also nach der Abarbeitung des Events geschehen. Richtig?
Jupp.

Gast hat gesagt.:
OK, wenn aber mein Event nun aber nichts mit der GUI zu tun hat? [...]
Genau dort liegt Dein Denkfehler. Der Event ist ein ActionEvent eines Buttons und gehört ganz genau zur GUI und zu nichts anderem. Wenn Du eine längere Operation ausführst gehört eben diese Operation nicht zur GUI und sollte deshalb eben nicht direkt im EventHandler ablaufen. Ich mache das normaler Weise so:
Code:
/** Action handler starting my long lasting action */
public void actionPerformed(ActionEvent event) {
  new Thread(new Runnable() {
    public void run() {
      myLongLastingAction();
    }
  }).start();
}

//...

void myLongLastingAction() {
  final int resultA;
  final int resultB;
  try {
    /* wait for ten seconds to simulate a complex calculation */
    Thread.sleep(10 * 1000);
    resultA = 23;
    resultB = 42;
  } catch (InterruptedException ex) {
    /* reset interrupt flag */
    Thread.currentThread().interrupt();
    return;
  }

  /* after calculation let the event dispatch thread update the GUI components */
  invokeOnEDT(new Runnable() {

    @Override
    public void run() {
      label.setText("Result A: " + resultA + " Result B: " + resultB);
    }
  });
}

/**
 * Runs the given runnable on the event dispatch thread and waits for the end
 * of processing before the method returns. If called on the EDT, the runnable's
 * {@code run()} method is simply called. If not called on the EDT, the
 * runnable is passed to the {@code SwingUtilities.invokeAndWait()} method.
 * Any unchecked exception is rethrown.
 *
 * @param doRun the runnable being executed
 */
private static void invokeOnEDTRunnable doRun) {
  if (SwingUtilities.isEventDispatchThread()) {
    doRun.run();
  } else {
    try {
      SwingUtilities.invokeAndWait(doRun);
    } catch (InterruptedException ex) {
      /* reset interrupted flag */
      Thread.currentThread().interrupt();
      return;
    } catch (InvocationTargetException ex) {
      final Throwable targetEx = ex.getTargetException();
      targetEx.fillInStackTrace();
      if (targetEx instanceof RuntimeException) {
        throw (RuntimeException) targetEx;
      } else if (targetEx instanceof Error) {
        throw (Error) targetEx;
      } else {
        assert false : "Must have been an unchecked exception!";
      }
    }
  }
}
In Java 6 (ich muss meist noch Java 5 benutzen und weiß daher nicht genau wie man's am besten nutzt) gibt es die SwingWorker-Klasse, mit der man das Problem ähnlich aber schöner lösen kann.

Ebenius
 
G

Gast

Gast
Hallo Ebenius,

danke für deine Geduld...

>Genau dort liegt Dein Denkfehler. Der Event ist ein ActionEvent >eines Buttons und gehört ganz genau zur GUI und zu nichts >anderem.

Das hab ich noch nicht ganz verstanden. Das Event gehört zwar zu einer Komponente (dem Button), also zur GUI, modifiziert doch aber in diesem Fall nicht das Aussehen bzw. den Status der GUI, d.h. ein neuzeichnen wäre in diesem Fall doch möglich, oder nicht. D.h. es ist ja nur kritisch, wenn die actionPerformedMethode eine Änderung an der GUI durchführen würde wie ein resize oder so...
 

Ebenius

Top Contributor
Es ist überhaupt nichts kritisch. Es ist eher ganz einfach... :)

Alle Events werden der Reihe nach aus einer Queue gezogen und abgearbeitet. Das ─ wenn man so will ─ oberste Event ist das was zur Zeit abgearbeitet wird. Während Dein Button-Handler arbeitet sieht die EventQueue dann bespielsweise so aus (stark vereinfacht und gekürzt):
Code:
ActionEvent on Button XYZ ← wird derzeit abgearbeitet
MouseEvent (MOUSE_RELEASED) on Button XYZ
PaintEvent on Button XYZ
...
Der PaintEvent wird erst dann bearbeitet werden, wenn die darüber liegenden Events abgearbeitet sind. Der oberste Punkt ist aber Deine laufende actionPerformed()-Methode und die hält alles andere in der EventQueue auf. Da geht es auch nicht um die Art der Tätigkeit der actionPerformed()-Methode (bezieht sich auf: "modifiziert doch aber in diesem Fall nicht das Aussehen ..."), sondern um den trivialen Fakt, dass ein Event Dispatch Thread nunmal nur eine Sache gleichzeitig machen kann.

Hilft das weiter?

Ebenius
 
G

Gast

Gast
Ja, ich glaub das hilft schon weiter. Du hattest ja weiter oben schon geschrieben, dass die Einführung eines seperaten Paint Thread problematisch ist, da die Events ja ggf. den Status der Komponente das Aussehen ändern. Das es mit der jetzigen Architektur nicht geht, da die Events nur in einem Thread abgearbeitet werden, ist mir auch klar. Aber wie ich schon sagte, wenn ich in meinem Event Handler nichts an der GUI ändere und z.B. nur was berechne, dann wäre es doch sinnvoll ein Zeichnen trotzdem anzustoßen, z.B. durch Einführung eines PaintThreads für genau diesen Fall.

Ich würde es so verstehen...

Die sequentielle Abarbeitung macht Sinn, da die Events größtenteils an der GUI was ändern und ein Zeichenthread somit sowieso warten müsste bis eine Statusänderung der Komponente durchgeführt wird.

Wenn ich jedoch in dem EventHandler nichts an der GUI ändere dann wäre es doch wünschenswert, dass eben genau für diesen Fall ein Zeichnen trotzdem "paralell" dazu erfolgen könnte.


Wie ich also oben schonmal schrieb:
>Viele Events führen zu einer Statusänderung der Komponente >welche mit einer visuellen Änderung der Komponente >einhergeht. Das zeichnen sollte also nach der Abarbeitung des >Events geschehen. Richtig?

Das ist klar und sinnvoll solange die Events was am Aussehen ändern. Wenn mein Event (Buttonklick) nun aber nichts am Aussehen der GUI ändert wäre es doch sinnvoll nun doch sowas wie einen PaintThread zu haben und nicht erst abzuwarten, bis die Methode (actionPerformed) abgearbeitet ist, z.B. um irgenwelche Meldungen auszugeben. Das macht wie gesagt ja nur dann Sinn, wenn wirklich nur Berechnungen durchgeführt werden...

Das es mit der momentanen Architketur (sequentielle Abarbeitung der Events im Dispatch Thread) so natürlich nicht geht hab ich denke ich verstanden. Aber die Frage ist, warum man eben gerade für den Fall falls man doch während ein Event abgearbeitet wird Zeichnen will, nicht eine Lösung eingeführt hat, wie z.B. den Zeichen Thread...
 
G

Gast

Gast
Nachtrag:

Bzgl. eines (Re)Paint Threads schriebst du ja oben:

>hätte drittens noch immer das Problem zur Folge, dass nicht >gezeichnet werden kann, während Nachrichten abgearbeitet >werden.

Das bezog sich ja darauf, dass er warten müsste wenn die Events (wie meistens der Fall) den Status der Komponente manipulieren welcher Auswirkungen auf die GUI hat. Wie gesagt, die Frage steht noch immer: Für diesen Fall leuchtet das ja ein, aber warum wird nicht ein "Spezialfall" zugelassen, wenn das Event dann doch nur "rechnet" und das keine Auswirkungen auf die GUI hat.

Übrigens nochmal ein grosses DANKE an dich Ebenius, dass du dein Wissen mit Anfängern teilst :)
 

Ebenius

Top Contributor
Es kann nicht so einfach getrennte Abarbeitung von Events und Zeichnen geben. Woher soll denn das AWT-Subsystem wissen, wann ein Event synchron und wann es asynchron abgearbeitet werden muss/kann/darf? Das kann doch keiner automatisch entscheiden. Die einzige Alternative die mir ad hoc dazu einfiele, wäre, alle Komponenten für jede Status-Änderung mit den Zeichenroutinen zu synchronisieren. Das ist aber
  • nicht nötig, da der fähige Entwickler gut auch selbst darüber entscheiden kann, wann er eine Operation auslagern muss/soll und wann nicht und
  • ein unerträglicher Mehraufwand, da ständig synchronisierte Bereiche betreten werden müssen, was eben teuer ist
Es gibt ja Widget-Konzepte die nicht auf einem Single-Thread-Modell aufbauen. In meinen Augen haben die sich nicht durchgesetzt, weil dadurch nichts einfacher sondern alles gefährlicher wird.

Anonymous hat gesagt.:
Übrigens nochmal ein grosses DANKE an dich Ebenius, dass du dein Wissen mit Anfängern teilst :)
Sehr gern. :)

Ebenius
 
G

Gast

Gast
Hallo Ebenius für die wie immer schnelle Antwort...

>Es kann nicht so einfach getrennte Abarbeitung von Events und >Zeichnen geben. Woher soll denn das AWT-Subsystem wissen, >wann ein Event synchron und wann es asynchron abgearbeitet >werden muss/kann/darf? Das kann doch keiner automatisch >entscheiden.

Das könnte doch der Programmierer beispielsweise mittels eines Schlüsselwortes o.ä. mitteilen

>ein unerträglicher Mehraufwand, da ständig synchronisierte >Bereiche betreten werden müssen, was eben teuer ist

Das verstehe ich nicht, vorallem das "teuer". Und wieso müssten in diesem Fall ständig synchronisierte Bereiche betreten werden?

Viele Grüße und Danke
 
G

Gast

Gast
Und bitte geh auch nochmal auf das
>weil dadurch nichts einfacher sondern alles gefährlicher wird.

ein
 

Ebenius

Top Contributor
Multi-Threading ist nie trivial, auch wenn einem Java mit Hilfe des synchronized-Schlüsselworts etwas anderes suggerieren mag. Sobald man mehrere Threads auf dieselben Daten loslässt, muss man zwischen den Zugriffen synchronisieren; das heißt, sicherstellen, dass nie einer schreibt während ein anderer die Daten liest oder auch schreibt. Dieser Aufwand ist zur Laufzeit teuer (synchronisierte Bereiche zu betreten kostet erheblich Zeit). Außerdem gibt es für den Programmierer mehr zu beachten, sobald er mit mehreren Threads arbeitet; darin bestehen die Gefahren. Schließlich ist das Thema ─ wie Du am Anfang dieses Threads nachlesen kannst ─ schon mit der Single-Thread-Philosophie schwierig genug; mit höherer Komplexität steigt dann auch das Risiko, Systeme zu benutzen die man nicht versteht.

Gast hat gesagt.:
Ebenius hat gesagt.:
Es kann nicht so einfach getrennte Abarbeitung von Events und Zeichnen geben. Woher soll denn das AWT-Subsystem wissen, wann ein Event synchron und wann es asynchron abgearbeitet werden muss/kann/darf? Das kann doch keiner automatisch entscheiden.
Das könnte doch der Programmierer beispielsweise mittels eines Schlüsselwortes o.ä. mitteilen
Zum Beispiel über Annotations wäre das prinzipiell möglich. Stellt sich aber noch immer die Frage, warum man das Problem auf diese Weise lösen sollte, wenn es doch mit dem SwingWorker ebenso einfach zu lösen ist.

Ebenius
 
G

Gast

Gast
Hallo Ebenius,

vielen Dank. Wirklich nett. Du solltest Dozent werden :)

Was ich noch nicht ganz verstanden habe:
>Dieser Aufwand ist zur Laufzeit teuer (synchronisierte Bereiche zu >betreten kostet erheblich Zeit). Außerdem gibt es für den >Programmierer mehr zu beachten, sobald er mit mehreren >Threads arbeitet; darin bestehen die Gefahren.
Wieso kostet es soviel Zeit synchronisierte Bereiche zu betreten und hast du noch ein Beispiel(szenario) was eine mögliche Gefahr wäre, wenn ich einen Event und einen Paint thread habe und vorher z.B. mittels "Schlüsselwort" dem thread mitgeteilt hätte "Du darfst zeichnen, da diese Methode die GUI nicht verändert"
 

Ebenius

Top Contributor
Vorab: Gewöhn Dir mal an, quote-Tags im Forum zu benutzen. Das liest sich gar grausam...

Gast hat gesagt.:
Wieso kostet es soviel Zeit synchronisierte Bereiche zu betreten
Es müssen zwei oder mehr Threads in einen Zustand gebracht werden in dem sichergestellt ist, dass nur einer der Threads den Bereich betreten und nicht zufällig zwei die es gleichzeitig probieren. Das kostet einfach auf jedem mir bekannten System Zeit.

Gast hat gesagt.:
hast du noch ein Beispiel(szenario) was eine mögliche Gefahr wäre, wenn ich einen Event und einen Paint thread habe und vorher z.B. mittels "Schlüsselwort" dem thread mitgeteilt hätte "Du darfst zeichnen, da diese Methode die GUI nicht verändert"
Da gibt es sicher tausend Varianten wie das schiefgehen kann. Aber da sauge ich mir jetzt mal nichts aus den Fingern, da es ein solches Konzept im Java nicht gibt.

Ebenius
 
G

Gast

Gast
Hallo Ebenius,

ich denke ich habe jetzt die meisten Probleme verstanden. Das grösste Problem ist also das sicherstellen der Konsistenz, wenn mehrere Threads statt nur der eine dispatch Thread konkurrieren.

Was ich jedoch noch nicht ganz verstanden habe:

Wenn ich meine langwierige Berechnung in einem seperaten Thread ausführe und in diesem Thread dann auch gleich das GUI update anstosse, wenn die Berechnung erfolgreich ist, sind dann die Logik (einfach einen Wert berechnen) und die GUI dann nicht miteinander verwoben (Thread muss GUI kennen um z.B. ein Label mit dem entsprechenden Wertz zu setzen)?

Wäre es nicht schöner ähnlich eines Methodenaufrufs, die Möglichkeit zu haben einfach nur den Wert zu berechnen unabhängig von einer (sich möglicherweise) ändernden GUI? D.h. wenn ich mein Ergebniss dann lieber in ein Textfeld schreiben will statt in ein Label muss ich ja im Berechnungsthread rumspielen...

Oder habe ich da wieder was falsch verstanden? ;-) Schonmal danke und einen schönen Freitag
 

Ebenius

Top Contributor
Schau Dir nochmal mein Code-Beispiel an: Dieses hier.
In den Zeilen 13 bis 24 ist die Berechnung. An dieser Stelle würde man die Trennung machen, also diese Zeilen rausschmeißen und auf die ausgelagerte Berechnungslogik verweisen. Also zum Beispiel sowas hier:
Code:
final Berechnung berechnung = new Berechnung();
berechnung.setEingabeWerte(meineEingangsWerte);
berechnung.run();
Der Aufbau und Start des Threads gehört in die GUI. Und das Auslesen und Darstellen der Ergebnisse aus der Berechnung sollte dann ein paar Zeilen weiter unten ebenfalls in der GUI passieren. Die Logik kann man aber schön in eine andere Klasse werfen.

So ergibt's Sinn, oder?

Ebenius
 
G

Gast

Gast
Hmm, ok. Also ich bräuchte dann noch sowas wie getEingabeWerte um die Werte für eine Darstellung in der GUI auszulesen?

Und noch ne andere Frage... Ich hab nocheinmal versucht über das Problem mit der Konsistenz bei einem seperaten Zeichen Thread nachgedacht...

angenommen ich würde in meiner Action performed Methode, wie ich es vorgeschlagen habe, mittels eines Schlüsselworts doch einen seperaten Zeichen Thread starten können (da dort z.B. wie bereits diskutiert keine GUI änderung stattfinden würde)... Der Thread würde dann laufen, bis der so markierte Bereich abgearbeitet ist. Da dürften doch keine Konsistenzprobleme entstehen, oder? Denn der Zeichen Thread würde ja nur konsistente Daten nutzen, da er duch die Schlüsselwörter "weiss", dass keine GUI relevanten Daten verändert wurden...

Nur mal so als Gedankenexperiment. Ich hoffe ich nerve dich nicht zu sehr ;-) Schönes WE und Danke
 

Ebenius

Top Contributor
Anonymous hat gesagt.:
Nur mal so als Gedankenexperiment. Ich hoffe ich nerve dich nicht zu sehr ;-) Schönes WE und Danke
Ehrlich? Es beginnt gerade... ;-) Für so viel Theorie hatte ich gestern zu viel Alkohol.

Ebenius
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
J Rekursive Methode JProgressBar AWT, Swing, JavaFX & SWT 4
T JProgressbar während actionListener updaten AWT, Swing, JavaFX & SWT 1
M Swing JProgressbar und Outoputstream probleme AWT, Swing, JavaFX & SWT 2
A Swing JProgressbar im Windows Look & Feel Farbanpassung AWT, Swing, JavaFX & SWT 2
G JProgressBar: Verständnis Problem AWT, Swing, JavaFX & SWT 3
S Swing JProgressBar läuft nicht mit AWT, Swing, JavaFX & SWT 12
T Swing JProgressBar mit String unschön AWT, Swing, JavaFX & SWT 5
H jprogressbar während datenabfrage anzeigen AWT, Swing, JavaFX & SWT 5
P Problem Thread.sleep() und JProgressBar AWT, Swing, JavaFX & SWT 7
E Swing JProgressBar updaten AWT, Swing, JavaFX & SWT 3
D Swing JProgressBar soll ende erkennen AWT, Swing, JavaFX & SWT 4
V Swing JProgressBar aktualisieren AWT, Swing, JavaFX & SWT 14
M JProgressBar updatet nicht AWT, Swing, JavaFX & SWT 4
T Swing JProgressBar Indeterminate bleibt stehen bei neuem Fenster AWT, Swing, JavaFX & SWT 6
A JProgressBar updaten abhängig vom Output eines externen Skripts AWT, Swing, JavaFX & SWT 2
M JProgressBar für einen Thread AWT, Swing, JavaFX & SWT 14
J JProgressBar Indeterminate AWT, Swing, JavaFX & SWT 17
J JProgressBar Farbverlauf AWT, Swing, JavaFX & SWT 2
O Probleme mit JProgressBar bei der Statusanzeige AWT, Swing, JavaFX & SWT 5
S jProgressbar von einem Download AWT, Swing, JavaFX & SWT 6
C Swing JProgressBar in JDialog wird nicht angezeigt AWT, Swing, JavaFX & SWT 6
S Swing StatusLeiste mit JProgressBar AWT, Swing, JavaFX & SWT 4
S JProgressBar in Abhängigkeit eines FileInputStreams AWT, Swing, JavaFX & SWT 2
S (Applets) JProgressBar wird erst am Ende angezeigt AWT, Swing, JavaFX & SWT 13
S Problem mit JProgressBar AWT, Swing, JavaFX & SWT 3
E Swing DB Zugriff mit JProgressBar?! AWT, Swing, JavaFX & SWT 8
C Swing JProgressBar Aktualisiert sich nicht. AWT, Swing, JavaFX & SWT 9
M JProgressBar Look and Feel AWT, Swing, JavaFX & SWT 5
C JProgressBar und JLabel AWT, Swing, JavaFX & SWT 5
K JProgressBar transparent AWT, Swing, JavaFX & SWT 10
M JProgressBar AWT, Swing, JavaFX & SWT 2
K JProgressBar für Serialisierung AWT, Swing, JavaFX & SWT 6
multiholle [JProgressBar] Raster deaktivieren AWT, Swing, JavaFX & SWT 14
M JProgressBar übereinander legen? AWT, Swing, JavaFX & SWT 3
B JProgressbar wird nicht aktualisert, trotz Threads AWT, Swing, JavaFX & SWT 6
S JProgressBar und Threads AWT, Swing, JavaFX & SWT 11
G Repaint bei JProgressBar AWT, Swing, JavaFX & SWT 3
A Richtiger Umgang mit jProgressBar AWT, Swing, JavaFX & SWT 2
H JProgressBar in TableColumn von JTable setzen/abfragen AWT, Swing, JavaFX & SWT 5
B JProgressBar: wie muss ich das lösen? AWT, Swing, JavaFX & SWT 4
R JProgressBar-Verhalten AWT, Swing, JavaFX & SWT 5
G JProgressbar AWT, Swing, JavaFX & SWT 8
A JProgressBar: Farbe im Windows Look&Feel ändern. AWT, Swing, JavaFX & SWT 1
C JProgressBar und ihre Tücken AWT, Swing, JavaFX & SWT 8
G JProgressBar in JTable AWT, Swing, JavaFX & SWT 6
G Probleme mit JProgressbar auf JPanel in JFrame AWT, Swing, JavaFX & SWT 6
F JProgressBar und NullPointerException AWT, Swing, JavaFX & SWT 4
T JProgressBar und CMP Bean AWT, Swing, JavaFX & SWT 2
J JProgressBar flackert AWT, Swing, JavaFX & SWT 14
S JProgressBar zu JOptionPane hinzufügen. AWT, Swing, JavaFX & SWT 8
M Swinganwendung Threads mit JProgressBar AWT, Swing, JavaFX & SWT 7
L JProgressbar möglichst genau AWT, Swing, JavaFX & SWT 3
G JProgressBar + Thread + Client AWT, Swing, JavaFX & SWT 10
R JProgressBar ohne Threads verwenden AWT, Swing, JavaFX & SWT 6
I JProgressBar String anzeigen, danach wieder normale Ansicht AWT, Swing, JavaFX & SWT 3
G JProgressBar AWT, Swing, JavaFX & SWT 8
L JProgressBar wird nicht mehr aktualisiert AWT, Swing, JavaFX & SWT 2
U JProgressBar in umgekehrter Richtung AWT, Swing, JavaFX & SWT 2
S JProgressBar einbinden AWT, Swing, JavaFX & SWT 5
H JProgressBar AWT, Swing, JavaFX & SWT 6
T JProgressBar und JPG AWT, Swing, JavaFX & SWT 2
D Problem mit JProgressBar und Threads AWT, Swing, JavaFX & SWT 7

Ähnliche Java Themen

Neue Themen


Oben