2009-12-16 10 views
13

Ich habe eine lange laufende Aufgabe, so etwas wie:Java lange laufende Aufgabe Thema unterbrechen vs Abbrechen Flagge

public void myCancellableTask() { 
    while (someCondition) { 
     checkIfCancelRequested(); 
     doSomeWork(); 
    } 
} 

Die Aufgabe abgebrochen werden kann (eine angeforderte cancel und checkIfCancelRequested() überprüft, die die Flagge abzubrechen). Wenn ich solche abbrechbaren Loops schreibe, benutze ich normalerweise ein Flag, um anzuzeigen, dass ein Cancel angefordert wurde. Aber ich weiß, dass ich auch Thread.interrupt verwenden kann und überprüfe, ob der Thread unterbrochen wurde. Ich bin mir nicht sicher, welches der bevorzugte Ansatz wäre und warum, Gedanken?

Dank,

Jeff

Antwort

6

Interrupt wird den Faden aus einer Liste der genannten Wartebedingungen sprengen. Ihre eigene Stornierungsmarkierung wird nicht angezeigt. Wenn Sie Wartezeiten auf E/A und Ereignisse unterbrechen möchten, verwenden Sie den Interrupt. Ansonsten benutze deine eigenen.

0

Ich denke, dass es in den meisten Fällen eine Frage der Präferenz ist. Persönlich würde ich für die handgemachte Flagge gehen. Es gibt Ihnen mehr Kontrolle - zum Beispiel stellen Sie sicher, dass Ihr Thread ein anderes Objekt nicht in einem inkonsistenten Zustand belässt. Wenn die Leistung wirklich kritisch ist, beachten Sie, dass die Verwendung von Ausnahmen einen Overhead hat (auch wenn es in 99% der Fälle vernachlässigbar ist).

1

Es hängt von der doSomeWork() Implementierung ab. Ist das reine Berechnung oder beinhaltet es (zu irgendeinem Zeitpunkt) das Blockieren von API-Aufrufen (z. B. IO)? Pro bmargulies Antwort, viele blockierende APIs in JDK sind unterbrechbar und wird die unterbrochene Ausnahme auf dem Stapel weiterleiten.

Also, wenn die Arbeit möglicherweise Aktivitäten blockiert bringt, need'll Sie Berücksichtigung Unterbrechungen in selbst zu nehmen, wenn Sie sich entscheiden, den Prozess zu steuern, um einen Flag verwendet, und soll entsprechend abfangen und behandeln/die Interrupts propagieren.

Darüber hinaus, wenn Sie sich auf ein Flag verlassen, stellen Sie sicher, dass Ihr Flag mit volatile Semantik deklariert ist.

20

Ein Problem bei Interrupt ist, dass wenn Sie ausgeführt nicht den gesamten Code steuern ist, können Sie das Risiko der Unterbrechung funktioniert nicht „richtig“ wegen jemand anderes laufen gebrochen zu verstehen, wie Interrupts zu behandeln in ihren Bibliothek. Das ist die API unsichtbar exportiert eine API um seine Handhabung von interrupt s, die Sie abhängig sind.

In Ihrem Beispiel nehmen doSomeWork in einer JAR-3rd-Party war und wie folgt aussieht:

public void doSomeWork() { 
    try { 
     api.callAndWaitAnswer() ; 
    } 
    catch (InterruptedException e) { throw new AssertionError(); } 
} 

Jetzt müssen Sie ein AssertionError (Sie verwenden könnten werfen oder was sonst auch immer die Bibliothek) behandeln. Ich habe erfahrene Entwickler gesehen, die beim Empfang von Interrupts alle möglichen Unsinnigkeiten geworfen haben! Auf der anderen Seite, vielleicht sah die Methode so aus:

Diese "unsachgemäße Behandlung" von Interrupt verursacht Ihr Programm auf unbestimmte Zeit Schleife. Auch dies ist nicht lächerlich; Es gibt viele gebrochene Interrupt-Handling-Mechanismen da draußen.

Zumindest die Verwendung Ihrer eigenen Flagge ist für Bibliotheken von Drittanbietern völlig unsichtbar.

+1

Gute Sachen hier. Es ist allzu üblich, das Schlucken des Interrupts zu sehen oder einfach nur zu protokollieren und fortzufahren, ohne das Interrupt-Flag zurückzusetzen. Ich denke, die Leute sind frustriert, dass es eine kontrollierte Ausnahme ist, mit der sie nicht wissen, was sie tun sollen, also machen sie überhaupt nichts. –

Verwandte Themen