PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Initial Thread und invokeLater



BlueJay
15-11-2011, 09:39
Hallo Leute,

ich habe da mal eine Verständnisfrage zur Main-Klasse und invokeLater:

Es ist ja so, dass für Main ein Initial-Thread gebildet wird. Wie lange lebt der im unteren Fall?



public class Main
{ final static String titel="Java-Experimente";
static JFrame my_frame;

public static void Main(String[] args)
{
javax.swing.SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
my_frame=new JFrame(titel);
my_frame.setDefaultCloseOperation(JFrame.EXIT_ON_C LOSE);
my_frame.setMinimumSize(new Dimension(480,360));
u.s.w.
..
..
my_frame.pack();
// ab da nur noch eventgetrieben bzw. mit eigenen Threads
}
}
// hier später noch ein bisschen zum Testen reingehängt
}

}

Kickt der einfach nur das Runnable an und ist dann weg (invokeLater)? Oder lebt der bis zum Programmende?
Lebt er bis zum Programmende, wenn man statt invokeLater invokeAndWait nimmt?

Wie wirkt invokeLater tatsächlich? Der hier gefundenen Sachverhalt im 1.Beispiel konnte von mir nicht bestätigt werden:
http://www.dpunkt.de/java/Programmieren_mit_Java/Oberflaechenprogrammierung/67.html

der Initial-Thread und der EventDispatchThread mit invokeLater arbeiteten fröhlich durcheinander.

Sorry, ich habe dazu so viel Artikel gelesen, die sich teilweise widersprachen sowie nicht zu meinen Testergebnissen passten, dass ich mal nachfragen muss.

Gruß,Ulrike

anda_skoa
16-11-2011, 08:59
Ist schon ein bischen her seit ich das letzte Mal Java benutzt habe, aber ich denke der Haupthread existiert so lange wie der Java Prozess läuft.

In Bezug auf die beiden Invoke Varianten würde ich davon ausgehen, dass beide das selbe "Invoke Event" benutzen, um den Aufruf an aktuell letzter Stelle in die Eventqueue einzuhängen.

D.h. der Eventthread wird das Invoke genau so behandlen als wäre eine Benutzerinteraktion zu diesem Zeitpunkt eingegangen, d.h. das Runnable.run() wird aufgerufen, sobald der Eventhread an diesem Punkt seiner Verarbeitungswarteschlange angelangt wird.

Im Falle der "AndWait" Variante wird das Abarbeiten der Events einfach direkt angetrieben, während im der Variante ohne Wait einfach der Haupteventschleife die Kontrolle überlassen wird.

In stark vereinfachter Form sieht das in etwa so aus



// run des Eventthread
void run() {
while (true) {
Event event = getEventFromQueue();
processOneEvent(event);
}
}

void processOneEvent(Event event) {
if ( event instanceOf EventA ) {
processEventA( (EventA) event );
} else if ( event instanceOf EventB ) {
processEventB( (EventB) event );
} else if ( event instanceOf InvokeEvent ) {
processInvoke (Invoke) event );
}
}

void processInvoke(InvokeEvent event) {
Runnable runnable = event.getRunnable();
runnable.run();
}

void processEventA(EventA event) {
invokeLater(new Runnable() { ... } )
}

void processEventB(EventB event) {
invokeLaterAndWair(new Runnable() { ... } )
}

void invokeLater(Runnable runnable) {
InvokeEvent invokeEvent = new InvokeEvent( runnable );
putEventIntoQueue( invokeEvent );
}

void invokeLaterAndWait(Runnable runnable) {
InvokeEvent invokeEvent = new InvokeEvent( runnable );
putEventIntoQueue( invokeEvent );
// so weit gleich wie invokeLater

// jetzt lokal Eventverarbeitung durchführen bis unser Event dran war
while (true) {
Event event = getEventFromQueue();
processOneEvent(event);
if (event == invokeEvent) break;
}
}


Ciao,
_

BlueJay
16-11-2011, 09:27
Soweit mir bekannt ist, sind Initial Thread und Event Dispatcher Thread zwei verschiedene Threads. Das deckt sich mit der Beobachtung, dass Anweisungen wom Initial-Thread und EDT fröhlich durcheinanderlaufen, wenn die Arbeitslisten entsprechend groß sind.

Mit


public static void checkthread()
{
if (javax.swing.SwingUtilities.isEventDispatchThread( )) System.out.println("löppt im EDT");
else System.out.println("löppt nicht im EDT");
}

lässt sich so was ja schnell herausfinden.

Das viel propagierte
invokeLater startet den Thread nämlich nicht, wenn der Initial Thread, wie meistens beschrieben, abgelaufen ist, sondern irgendwann, wenn es dazwischenfunken kann. Ausgerechnet bei Sun/Oracle findet man teilweise diese irreführenden Aussagen! Und dann wird nicht erklärt, dass das höchstens so ist, wennd der Initial Thread nix weiter als den EDT anzustoßen hat. Damit ist das Ganze ein Timing-Problem, was meistens gutgeht, aber nur meistens! (ich bin hier mal pingelig!)

Nun ist es ja so, dass man Methoden schreiben kann, die aus einem Thread irgendeinen Thread ankicken und dann normal weiterlaufen und sich beenden, während der angekickte Thread noch lebt.

Meine Frage: macht das der Initial Thread auch? Verdrückt er sich, wenn er abgearbeitet ist? Oder behält er die Kontrolle, bis sich hier der später invokte Thread verabschiedet hat? (kriegt eine "Extrawurst" gebraten)

Für die Praxis heisst das natürlich, dass bei mir der Initial Thread bis auf das Ankicken des EDT nackt bleibt.

Gruß,
Ulrike


Habe inzwischen via Suche nach VM die Lösung bekommen: da hat sich wohl zwischendurch die Architektur geändert. Derzeit ist es so, dass der Initial Thread so lange bestehen bleibt, wie Nicht-Dämon-Threads laufen, und verabschiedet sich erst dann. Er beendet sich sofort, wenn er von einem der Threads ein Exit abbekommt.

Eventuell gestartete Dämon-Threads laufen nach Verabschieden des Initial Threads weiter. Da der EDT meist nicht als Dämon-Thread gestartet wird, dürfte der Initial Thread wohl die ganze Laufzeit leben.


d.h., der von anda_skoa vermutete Sachverhalt ist (derzeit?) tatsächlich so.