

Die vorliegende Übersetzung wurde maschinell erstellt. Im Falle eines Konflikts oder eines Widerspruchs zwischen dieser übersetzten Fassung und der englischen Fassung (einschließlich infolge von Verzögerungen bei der Übersetzung) ist die englische Fassung maßgeblich.

# Eine Aufgabe in AWS Flow Framework für Java verstehen
<a name="details"></a>

**Topics**
+ [Aufgabe](#details.task)
+ [Reihenfolge der Ausführung](#details.order)
+ [Workflow-Ausführung](#details.workflow)
+ [Nichtdeterminismus](#details.non)

## Aufgabe
<a name="details.task"></a>

Das zugrunde liegende Primitiv, das AWS Flow Framework for Java verwendet, um die Ausführung von asynchronem Code zu verwalten, ist die `Task` Klasse. Ein Objekt vom Typ `Task` stellt Arbeit dar, die asynchron durchgeführt werden muss. Wenn Sie eine asynchrone Methode aufrufen, erzeugt das Framework eine `Task`, um den Code in dieser Methode auszuführen, und setzt ihn in eine Liste für eine Ausführung zu einem späteren Zeitpunkt. Ebenso wird beim Aufruf einer `Activity` eine `Task` dafür erstellt. Der Methodenaufruf wird danach zurückgegeben, in der Regel mit einem `Promise<T>` als zukünftiges Ergebnis des Aufrufs.

Die `Task`-Klasse ist öffentlich und kann direkt verwendet werden. Wir können beispielsweise das Beispiel „Hello World“ so neu schreiben, dass es eine `Task` anstatt einer asynchronen Methode verwendet.

```
@Override
public void startHelloWorld(){
       final Promise<String> greeting = client.getName();
        new Task(greeting) {
        @Override
        protected void doExecute() throws Throwable {
        	client.printGreeting("Hello " + greeting.get() +"!");
        }
    };
}
```

Das Framework ruft die `doExecute()`-Methode auf, wenn alle `Promise`s, die an den Konstruktor der `Task` übergeben wurden, einsatzbereit sind. Weitere Informationen zur `Task` Klasse finden Sie in der AWS SDK für Java Dokumentation.

Das Framework umfasst auch eine Klasse mit der Bezeichnung `Functor`, die eine `Task` darstellt, die auch ein `Promise<T>` ist. Das `Functor`-Objekt ist einsatzbereit, wenn die `Task` abgeschlossen wird. Im folgenden Beispiel wird ein `Functor` erstellt, um die Begrüßungsnachricht abzurufen:

```
Promise<String> greeting = new Functor<String>() {
    @Override
    protected Promise<String> doExecute() throws Throwable {
        return client.getGreeting();
    }
};
client.printGreeting(greeting);
```

## Reihenfolge der Ausführung
<a name="details.order"></a>

Aufgaben werden nur für die Ausführung berechtigt, wenn alle `Promise<T>`-typisierten Parameter, die an die entsprechende asynchrone Methode oder Aktivität übergeben wurden, einsatzbereit sind. Eine zur Ausführung bereite `Task` wird logisch eine eine einsatzbereite Warteschlange verschoben. Mit anderen Worten wird sie für die Ausführung geplant. Die Worker-Klasse führt die Aufgabe aus, indem sie den Code aufruft, den Sie in den Hauptteil der asynchronen Methode geschrieben haben, oder indem sie im Fall einer Aktivitätsmethode eine Aktivitätsaufgabe in Amazon Simple Workflow Service (AWS) plant. 

Wenn Aufgaben ausgeführt werden und Ergebnisse erzielen, sorgen sie dafür, dass andere Aufgaben einsatzbereit werden, und die Ausführung des Programms schreitet weiter voran. Die Art und Weise, wie das Framework Aufgaben ausführt, ist wichtig, um die Reihenfolge zu verstehen, in der Ihr asynchroner Code ausgeführt wird. Code, der sequenziell in Ihrem Programm erscheint, wird möglicherweise nicht tatsächlich in dieser Reihenfolge ausgeführt.

```
Promise<String> name = getUserName();
printHelloName(name);
printHelloWorld();
System.out.println("Hello, Amazon!");

@Asynchronous
private Promise<String> getUserName(){
	return Promise.asPromise("Bob");
}
@Asynchronous
private void printHelloName(Promise<String> name){
	System.out.println("Hello, " + name.get() + "!");
}
@Asynchronous
private void printHelloWorld(){
	System.out.println("Hello, World!");
}
```

Der Code in der Auflistung oben wird wie folgt gedruckt:

```
Hello, Amazon!
Hello, World!
Hello, Bob
```

Dies ist möglicherweise nicht das, was Sie erwarten. Dies kann aber einfach erklärt werden, indem Sie durchdenken, wie die Aufgaben für die asynchronen Methoden ausgeführt wurden:

1. Der Aufruf von `getUserName` erzeugt eine `Task`. Nennen wir sie `Task1`. Weil `getUserName` es keine Parameter akzeptiert, `Task1` wird es sofort in die Bereitschaftswarteschlange gestellt.

1. Anschließend erzeugt der Aufruf von `printHelloName` eine `Task`, die auf das Ergebnis von `getUserName` warten muss. Nennen wir sie `Task2`. Weil der erforderliche Wert noch nicht bereit ist, `Task2` wird er auf die Warteliste gesetzt.

1. Dann wird eine Aufgabe für` printHelloWorld` erstellt und zur einsatzbereiten Warteschlange hinzugefügt. Nennen wir sie `Task3`.

1. `println`In der Erklärung wird dann „Hello, Amazon\$1“ gedruckt zur Konsole.

1. An diesem Punkt befinden sich `Task1` und `Task3` in der einsatzbereiten Warteschlange und `Task2` befindet sich in der Warteliste.

1. Der Worker führt `Task1` aus. Durch das Ergebnis wird `Task2` vorbereitet. `Task2` wird der Bereitschaftswarteschlange hinter `Task3` hinzugefügt.

1. `Task3` und `Task2` werden dann in dieser Reihenfolge ausgeführt.

Die Ausführung der Aktivitäten folgt dem gleichen Muster. Wenn Sie eine Methode auf dem Aktivitätsclient aufrufen, wird eine erstellt, `Task` die bei der Ausführung eine Aktivität in Amazon SWF plant.

Das Framework nutzt Funktionen, wie Code-Generierung und dynamische Proxys, um die Logik für die Konvertierung von Methodenaufrufen in Aktivitätsaufrufe und asynchrone Aufgaben in Ihrem Programm einzufügen.

## Workflow-Ausführung
<a name="details.workflow"></a>

Die Ausführung der Workflow-Implementierung wird auch von der Worker-Klasse verwaltet. Wenn Sie eine Methode auf dem Workflow-Client aufrufen, ruft sie Amazon SWF auf, um eine Workflow-Instanz zu erstellen. Die Aufgaben in Amazon SWF sollten nicht mit den Aufgaben im Framework verwechselt werden. Eine Aufgabe in Amazon SWF ist entweder eine Aktivitätsaufgabe oder eine Entscheidungsaufgabe. Die Ausführung einer Aktivitätsaufgabe ist einfach. Die Activity Worker-Klasse empfängt Aktivitätsaufgaben von Amazon SWF, ruft die entsprechende Aktivitätsmethode in Ihrer Implementierung auf und gibt das Ergebnis an Amazon SWF zurück.

Die Ausführung der Entscheidungsaufgaben ist komplexer. Der Workflow-Worker erhält Entscheidungsaufgaben von Amazon SWF. Eine Entscheidungsaufgabe ist effektiv eine Anfrage, die die Workflow-Logik fragt, was als Nächstes zu tun ist. Die erste Entscheidungsaufgabe wird für eine Workflow-Instance generiert, wenn sie über den Workflow-Client gestartet wird. Beim Empfang dieser Entscheidungsaufgabe beginnt das Framework mit der Ausführung des Codes in der Workflow-Methode, die mit `@Execute` versehen ist. Diese Methode führt die Koordinationslogik aus, die Aktivitäten plant. Wenn sich der Status der Workflow-Instanz ändert, z. B. wenn eine Aktivität abgeschlossen ist, werden weitere Entscheidungsaufgaben geplant. An diesem Punkt kann die Workflow-Logik entscheiden, eine Aktion basierend auf dem Ergebnis der Aktivität auszuführen, zum Beispiel kann sie entscheiden, eine andere Aktivität zu planen.

Das Framework blendet alle diese Details vom Entwickler aus, indem Entscheidungsaufgaben nahtlos in die Workflow-Logik übertragen werden. Aus der Sicht eines Entwicklers sieht der Code einfach wie ein reguläres Programm aus. Unter dem Deckmantel ordnet das Framework es Aufrufen von Amazon SWF und Entscheidungsaufgaben zu und verwendet dabei den von Amazon SWF verwalteten Verlauf. Wenn eine Entscheidungsaufgabe eintrifft, gibt das Framework die Programmausführung erneut wieder, wobei die Ergebnisse der bisher abgeschlossenen Aktivitäten eingefügt werden. Asynchrone Methoden und Aktivitäten, die auf diese Ergebnisse gewartet haben, werden entsperrt und die Programmausführung geht weiter.

Die Ausführung des Beispiel-Bildverarbeitungs-Workflows und des entsprechenden Verlaufs werden in der folgenden Tabelle gezeigt.


**Ausführung des Thumbnail-Workflows**  

| Workflow-Programmausführung | Von Amazon SWF verwalteter Verlauf  | 
| --- | --- | 
| Anfängliche Ausführung | 
|  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/de_de/amazonswf/latest/awsflowguide/details.html)  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/de_de/amazonswf/latest/awsflowguide/details.html)  | 
| Erneut abspielen | 
|  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/de_de/amazonswf/latest/awsflowguide/details.html)  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/de_de/amazonswf/latest/awsflowguide/details.html)  | 
| Erneut abspielen | 
|  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/de_de/amazonswf/latest/awsflowguide/details.html)  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/de_de/amazonswf/latest/awsflowguide/details.html)  | 
| Erneut abspielen | 
|  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/de_de/amazonswf/latest/awsflowguide/details.html)  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/de_de/amazonswf/latest/awsflowguide/details.html)  | 

Wenn ein Aufruf von `processImage` erfolgt, erstellt das Framework eine neue Workflow-Instanz in Amazon SWF. Dies ist ein dauerhafter Datensatz der gestarteten Workflow-Instance. Das Programm wird bis zum Aufruf der `downloadImage` Aktivität ausgeführt, wodurch Amazon SWF aufgefordert wird, eine Aktivität zu planen. Der Workflow wird weiter ausgeführt und erstellt Aufgaben für nachfolgende Aktivitäten. Sie können jedoch erst ausgeführt werden, wenn die `downloadImage` Aktivität abgeschlossen ist. Somit endet diese Episode der Wiederholung. Amazon SWF sendet die Aufgabe für die `downloadImage` Aktivität zur Ausführung. Sobald sie abgeschlossen ist, wird zusammen mit dem Ergebnis ein Eintrag in der Historie erstellt. Der Workflow ist jetzt bereit, fortzufahren, und eine Entscheidungsaufgabe wird von Amazon SWF generiert. Das Framework empfängt die Entscheidungsaufgabe und wiederholt den Workflow, wobei das Ergebnis des heruntergeladenen Abbilds wie im Verlauf aufgezeichnet eingefügt wird. Dadurch wird die Blockierung der Aufgabe für `createThumbnail` aufgehoben, und die Ausführung des Programms wird weiter fortgesetzt, indem die `createThumbnail` Aktivitätsaufgabe in Amazon SWF geplant wird. Derselbe Prozess wird für `uploadImage` wiederholt. Die Ausführung des Programms geht auf diese Weise weiter, bis der Workflow alle Abbilder verarbeitet hat und es keine ausstehenden Aufgaben gibt. Da kein Ausführungsstatus lokal gespeichert ist, kann jede Entscheidungsaufgabe möglicherweise auf einem anderen Computer ausgeführt werden. Dadurch können Sie ganz einfach Programme schreiben, die fehlertolerant und problemlos skalierbar sind.

## Nichtdeterminismus
<a name="details.non"></a>

Da das Framework auf der Wiedergabe basiert, ist es wichtig, dass der Orchestrierungscode (der gesamte Workflow-Code mit Ausnahme von Aktivitätsimplementierungen) deterministisch ist. Beispielsweise sollte der Steuerungsfluss in Ihrem Programm nicht von einer zufälligen Zahl oder der aktuellen Zeit abhängen. Da sich diese Dinge zwischen Aufrufen ändern, folgt die Wiedergabe möglicherweise nicht demselben Pfad durch die Orchestrierungslogik. Dies führt zu unerwarteten Ergebnissen oder Fehlern. Das Framework bietet einen `WorkflowClock`, den Sie verwenden können, um die aktuelle Zeit auf deterministische Weise abzurufen. Weitere Informationen finden Sie im Abschnitt zu [Ausführungskontext](executioncontext.md). 

**Anmerkung**  
Eine falsche Spring-Verdrahtung der Workflow-Implementierungsobjekte kann auch zu Nichtdeterminismus führen. Workflow-Implementierungs-Beans sowie Beans, von denen sie abhängig sind, müssen sich im Workflow-Umfang (`WorkflowScope`) befinden. Beispielsweise führt das Vertraten einer Workflow-Implementierungs-Bean mit einer Bean, die den Zustand behält und sich im globalen Kontext befindet, zu unerwartetem Verhalten. Weitere Details finden Sie im Abschnitt [Spring-Integration](test.md#test.spring).