2016-04-04 10 views
1

Verzeihen Sie meine Ignoranz, wenn dies eine grundlegende Frage ist.Hintergrund Verarbeitung Java

Ich möchte verstehen, wie kann ich die Steuerung von einem Modul zurückgeben und die Verarbeitung im Hintergrund starten?

Lets starten Komponente A ruft Komponente B auf. Komponente B führt einige grundlegende Verarbeitung aus, startet einen Hintergrundthread und gibt sofort die Steuerung an A zurück. Wenn der Hintergrundthread seine Verarbeitung beendet, speichert er das Ergebnis in einem Persistenzspeicher. Die gesamte Verarbeitung durch diesen Hintergrund-Thread ist zeitaufwendig und A kann nicht warten, bis der Hintergrund-Thread beendet ist.

Component A { 
    Http Call component B 
} 

Component B { 
    // Got request from component A 
    start background thread(); 
    return; // don't wait till background thread finishes off 
} 

background thread() { 
// time consuming task 
} 

Wie kann ich dieses Verhalten in Java erreichen? Ich glaube nicht, dass es sich um eine völlig asynchrone Form der Verarbeitung handelt, da die Kommunikation über eine HTTP-Verbindung mit Timeout-Einstellungen stattfindet.

Update:

Component A: 
Receives Http call 


Component B: 

Approach1: 

Runnable runnable = new MyThread(); 
new Thread(runnable).start(); 

Approach2: 

ExecutorService exec = Executors.newSingleThreadExecutor(); 
exec.execute(new MyThread()); 
exec.shutdown(); 

Sie die HTTP-Aufruf zurück Beide oben genannten Ansätze hat mir geholfen, die Hintergrundverarbeitung zu starten und das Rück sofortige Kontrolle zu A.

+0

Haben Sie die Nebenläufigkeit Dienstprogramme betrachtet? Wenn nicht, schauen Sie hier: https://docs.oracle.com/javase/tutorial/essential/concurrency/runthread.html – Bajal

Antwort

1

Verwenden Gewinde ist für einige einfache proof of concepts gute Lösung, aber ich empfehlen dringend zumindest versuchen, die gleichzeitige API von Java zu verwenden, finden Sie die Dokumentation here. und ein gutes Tutorial ist here

Der einfachste Ansatz besteht darin, ein Callable-Objekt zu erstellen, das die Anweisung enthält, die Sie im Hintergrund ausführen möchten.

Callable myInstructions = new Callable<ObjectToReturn>() { 
     public ObjectToReturncall() { 
      return object.methodCall(); 
     }} 

Mit dem ExecutorService dieses aufrufbar senden Sie eine Zukunft Objekt zu erwarten.

Zukünftige API haben eine Reihe von Methoden zu fragen, ob die Aufgabe bereits abgeschlossen ist.

if(future.isDone()) // Ask if the task is done 
    ObjectToReturn solution = future.get() // Get the result 

Sehr einfach in die Zukunft API zu verwenden.

EDIT

Wenn Sie irgendeine Antwort von der Zukunft api nicht erwarten, nicht nur eine Operation Sie

Future<Void> future = executor.submit(new Callable<Void>() { 
    public Void call() throws Exception { 
     testA.abc(); 
     return null; 
    } 
}); 

Andere Option verwenden können, wenn Sie nicht wollen, um ein Ergebnis erhalten oder eine Antwort erhalten , Feuer nur ein Thread

ExecutorService executor = Executors.newFixedThreadPool(5);` 
executor.execute(new RunnableClass()); 

auch Anruf Abschaltung vermeiden auf ExecutorService, tun das nur sein, bis Das Ende des Prozesses, wenn Sie nicht mehr Zeit haben, im Frühjahr oder Container fwks der Container ist verantwortlich für das Herunterfahren der ExecutorService, sobald die App heruntergefahren wurde

+0

Vielen Dank für Ihre Antwort. Ich werde es ausprobieren. – user3505394

+0

Hey, ich konnte dies mit den beiden oben aufgeführten Ansätzen implementieren. Können Sie mir vorschlagen, dass dies hier richtig ist? Ich möchte kein Ergebnis erhalten, also nicht abrufbar. – user3505394

+0

Ich bin mir auch nicht sicher, ob das Herunterfahren des Executor-Dienstes richtig zu tun ist oder nicht. Da meine Komponente A einen http-Aufruf mehrmals erhalten wird, wird bei jedem Anruf ein Hintergrundthread zur Verarbeitung gestartet und dann der Executorservice heruntergefahren. Auch Komponente A kann den Aufruf parallel ausführen. – user3505394

0

Angenommen wollen, bevor die Hintergrundverarbeitung abgeschlossen ist , Ihr Pseudocode ist perfekt für Java gültig.

Auf der nächsten Detailebene, überprüfen Sie die Javadoc für Thread, Runnable und die java.nio Bibliothek Klassen.

0

Der einfachste Weg wäre wahrscheinlich, ein neues Java Thread mit der Hintergrundverarbeitungslogik als Parameter zu erstellen.

void componentB() { 
    new Thread(new Runnable() { 
     @Override 
     public void run() { 
      // Time consuming task. 
     } 
    }).start(); 
    // The method continues without stopping. 
} 

In späteren Versionen von Java, können Sie auch die ForkJoinPool -Klasse verwenden, um dies zu erreichen: in einem rohen Ebene

public class Main { 

    private final ExecutorService executor = new ForkJoinPool(); 

    void componentA() { 
     componentB(); 
    } 

    void componentB() { 
     executor.execute(this::timeConsumingTask); 
     // The method continues without stopping. 
    } 

    private void timeConsumingTask() { 
     // Time consuming task. 
    } 
}