webentwicklung-frage-antwort-db.com.de

Java Warten Sie, bis der Thread beendet ist

Ich habe einen Thread, der Daten herunterlädt, und ich möchte warten, bis der Download abgeschlossen ist, bevor ich die Daten lade. Gibt es eine Standardmethode dafür?

Mehr Info:

Ich habe eine Download-Klasse, die Daten von einer URL abruft (Serialized POJOs). Download ist lauffähig und beobachtbar. Es verfolgt die heruntergeladenen Bytes und die Downloadgröße. Ich habe einen Fortschrittsbalken, der dem Benutzer den Fortschritt anzeigt. Die GUI beobachtet Download, um den Fortschrittsbalken zu aktualisieren.

Wenn das POJO heruntergeladen ist, möchte ich es herunterladen und mit dem nächsten Schritt fortfahren. Jeder Schritt muss warten, bis der vorherige abgeschlossen ist. Das Problem ist, dass ich mir keine Möglichkeit vorstellen kann, meine Anwendung anzuhalten, um auf den Download-Thread zu warten. Sobald der Download abgeschlossen ist, möchte ich download.getObject () aufrufen, das die Daten als Objekt zurückgibt. Ich kann es dann besetzen und mit dem nächsten Download weitermachen.

Ich habe eine Hilfsklasse, die die URLs zum Herunterladen verwaltet und alle Aufrufe zum Herunterladen vornimmt. Dieser Aufruf ruft getObject auf und führt das Casting durch. Die GUI ruft helper.getUser () auf. helper startet den Thread und möchte, dass er 'weiß', wann er fertig ist, damit er das gegossene Objekt zurückgeben kann.

Anregungen/Beispiele? Ich bin in den Anfängen dieses Entwurfs, also bin ich bereit, es zu ändern.

Dankesehr.

Update:

Ich folgte http://download.Oracle.com/javase/6/docs/api/javax/swing/SwingWorker.html#get und verwendete modal, um zu blockieren, bis der Thread beendet war. Der Code war sehr chaotisch und ich mag diesen Ansatz nicht. Ich werde weiterhin versuchen, einen "sauberen" Weg zu finden, um den Workflow der Download-Prozesse zu handhaben.

53
Allan

Thread hat eine Methode, die das für Sie erledigt join , die blockiert, bis der Thread die Ausführung beendet hat.

68
unholysampler

Sie können ein CountDownLatch aus dem Paket Java.util.concurrent Verwenden. Dies ist sehr nützlich, wenn Sie darauf warten, dass ein oder mehrere Threads abgeschlossen sind, bevor Sie die Ausführung im wartenden Thread fortsetzen.

Warten Sie beispielsweise, bis drei Aufgaben abgeschlossen sind:

CountDownLatch latch = new CountDownLatch(3);
...
latch.await(); // Wait for countdown

Die anderen Threads rufen dann jeweils latch.countDown() auf, wenn sie mit ihren Aufgaben fertig sind. Sobald der Countdown abgeschlossen ist (in diesem Beispiel drei), wird die Ausführung fortgesetzt.

51
permagnusson

SwingWorker hat doInBackground(), mit dem Sie eine Aufgabe ausführen können. Sie haben die Möglichkeit, get() aufzurufen und zu warten, bis der Download abgeschlossen ist, oder Sie können die done() -Methode überschreiben, die nach Abschluss von SwingWorker für den Event-Dispatch-Thread aufgerufen wird.

Der Swingworker hat gegenüber Ihrem derzeitigen Ansatz den Vorteil, dass er viele der Funktionen bietet, nach denen Sie suchen, sodass Sie das Rad nicht neu erfinden müssen. Sie können die Methoden getProgress() und setProgress() als Alternative zu einem Beobachter auf der ausführbaren Datei für den Download-Fortschritt verwenden. Die oben angegebene done() -Methode wird aufgerufen, nachdem der Worker die Ausführung beendet hat und wird auf dem EDT ausgeführt. Auf diese Weise können Sie die Daten laden, nachdem der Download abgeschlossen ist.

13
tstevens

Im Laufe der Zeit wurden bessere Alternativen zu join () entwickelt.

ExecutorService.html # invokeAll ist eine Alternative.

Führt die angegebenen Aufgaben aus und gibt eine Liste der Futures zurück, die ihren Status und ihre Ergebnisse enthalten, wenn alle abgeschlossen sind. Future.isDone () ist für jedes Element der zurückgegebenen Liste wahr.

Beachten Sie, dass eine abgeschlossene Aufgabe entweder normal oder durch Auslösen einer Ausnahme beendet werden konnte. Die Ergebnisse dieser Methode sind nicht definiert, wenn die angegebene Auflistung geändert wird, während dieser Vorgang ausgeführt wird.

ForkJoinPool oder Executors.html # newWorkStealingPool bietet andere Alternativen, um denselben Zweck zu erreichen.

Beispielcode-Snippet:

import Java.util.concurrent.*;

import Java.util.*;

public class InvokeAllDemo{
    public InvokeAllDemo(){
        System.out.println("creating service");
        ExecutorService service = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());

        List<MyCallable> futureList = new ArrayList<MyCallable>();
        for ( int i=0; i<10; i++){
            MyCallable myCallable = new MyCallable((long)i);
            futureList.add(myCallable);
        }
        System.out.println("Start");
        try{
            List<Future<Long>> futures = service.invokeAll(futureList);  
        }catch(Exception err){
            err.printStackTrace();
        }
        System.out.println("Completed");
        service.shutdown();
    }
    public static void main(String args[]){
        InvokeAllDemo demo = new InvokeAllDemo();
    }
    class MyCallable implements Callable<Long>{
        Long id = 0L;
        public MyCallable(Long val){
            this.id = val;
        }
        public Long call(){
            // Add your business logic
            return id;
        }
    }
}
8
Ravindra babu

Sie können join() verwenden, um zu warten, bis alle Threads beendet sind. Behalten Sie alle Objekte von Threads in der globalen ArrayList bei, wenn Sie Threads erstellen. Danach halten Sie es in der Schleife wie folgt:

for (int i = 0; i < 10; i++) 
{
    Thread T1 = new Thread(new ThreadTest(i));                
    T1.start();                
    arrThreads.add(T1);
} 

for (int i = 0; i < arrThreads.size(); i++) 
{
    arrThreads.get(i).join(); 
}

Überprüfen Sie hier für vollständige Details: http://www.letmeknows.com/2017/04/24/wait-for-threads-to-finish-Java

5
user7923798

Ich stelle mir vor, dass Sie Ihren Download in einem Hintergrund-Thread aufrufen, wie er von einem SwingWorker bereitgestellt wird. Wenn ja, rufen Sie einfach Ihren nächsten Code nacheinander in derselben doInBackground-Methode von SwingWorker auf.

Wenn Sie auf das Ende eines Threads warten möchten, sollten Sie im Allgemeinen join () aufrufen.

3
biziclop

Anregungen/Beispiele? Ich folgte SwingWorker ... Der Code war sehr chaotisch und ich mag diesen Ansatz nicht.

Verwenden Sie anstelle von get(), das auf den Abschluss wartet, process() und setProgress(), um Zwischenergebnisse anzuzeigen, wie in diesem einfachen Beispiel oder vorgeschlagen diesbezüglich Beispiel .

1
trashgod

Die join () -Methode ermöglicht es einem Thread, auf den Abschluss eines anderen Threads zu warten. Wie beim Energiesparmodus ist der Join jedoch vom Betriebssystem abhängig, sodass Sie nicht davon ausgehen sollten, dass der Join genau so lange wartet wie Sie angeben.

0
Jatin Mandanka