2009-05-16 4 views
2

Ich versuche, meinen Haupt-Thread aus einem neuen Thread spawnen und nach einiger Zeit die Interrupt-Flag zu erhöhen. Wenn dies der Fall ist, sollte der erzeugte Thread dieses Flag sehen und sich selbst beenden.Threading in Java

Der Haupt-Thread sieht wie folgt aus etwas:

final Thread t = new Thread() 
{ 
    @Override 
    public void run() 
    { 
     f(); 
    } 
}; 
t.start(); 
try 
{ 
    t.join(time); 
    t.interrupt(); 
    if(t.isAlive()) 
    { 
     t.join(allowance); 
     if(t.isAlive()) 
      throw new Exception(); 
    } 
} 
catch(Exception e) 
{ 
    System.err.println("f did not terminate in the alloted time"); 
} 

Und der erzeugte Thread hat ein Bündel der während seiner gesamten Code verstreut folgende:

if(Thread.interrupted()) return; 

Wenn ich im Debug-Modus, alles funktioniert perfekt. Das Unterbrechungsflag wird vom Hauptthread ausgelöst und vom gespawnten Thread abgefangen. Im regulären Ausführungsmodus scheint jedoch der erzeugte Thread das Unterbrechungsflag nicht zu empfangen, egal wie lange ich die Toleranz festlege.

Weiß jemand, was ich falsch mache?

Hinweis: Ich benutze Ubuntu und bin zu allem Linux neu. Kann das Problem mit dem Betriebssystem auftreten? Ich habe den Code auf keinem anderen Betriebssystem getestet.

+0

Wird die Nachricht "f wurde nicht in der zugewiesenen Zeit beendet?" Gedruckt? –

+0

f ist eine Funktion, die für immer ausgeführt wird, wenn die Möglichkeit gegeben wird. Also ist die Erlaubnis die Zeit, die f benötigt, um den Interrupt zu erfassen und zu beenden. Außerdem wird die Nachricht gedruckt, wenn die Erlaubniszeit abgelaufen ist. – user108088

+0

Wenn Ihre Funktion eine Weile ist (true), sollten Sie die Bedingung ändern, wenn Sie überprüfen, ob der Thread unterbrochen ist. –

Antwort

0

Ich schlage vor, dass Sie in Erwägung ziehen, einen ExecutorService zu verwenden, der für diese Art von Aufgabe entwickelt wurde und Ihnen auf andere Weise helfen könnte.

ExecutorService service = Executors.newCachedThreadPool(); 
Future<ResultType> future = service.submit(new Callable<ResultType() { 
    public ResultType call() throws Exception { 
     // do soemthing 
     return (ResultType) ...; 
    } 
); 
// do anything you like until you need to result. 
try { 
    ResultType result = future.get(5, TimeUnit.SECONDS); 
} catch (TimeoutException timedOut) { 
    // handle exception 
    // cancel the task, interrupting if still running. 
    result.cancel(true); 
} catch (ExecutionException taskThrewAnException) { 
    // handle exception 
} 
// when you have finished with the service, which is reusable. 
service.shutdown(); 
0

Es sieht so aus, als ob der Aufruf Thread.interrupted() in f() nicht erreicht wird.

Das unterschiedliche Verhalten, das Sie im Debug- und im Run-Modus sehen, ist wahrscheinlich auf eine Racebedingung zurückzuführen.

4

Hier sind meine Vermutungen:

  • Wenn Haupt-Thread ruft t.interrupt(); die t Thread-Ausführung bereits beendet ist.
  • Wenn der Hauptthread t.interrupt(); im t-Thread aufruft, gibt es keine weiteren Aufrufe zur Überprüfung interrupted() Flag.
  • Sie erhalten die Ausnahme als Folge der Ausführung des Codes? Erhalten Sie die Ausnahme, die Sie in Ihren Code nach "Erlaubnis" Zeit werfen oder haben Sie andere wie ThreadInterruptedException oder ähnliches? Versuchen Sie, die Nachricht der abgefangenen Ausnahme zu schreiben ...
+0

+1 für Ihren zweiten Punkt –

+0

* Wenn t vor dem Interrupt abgeschlossen wurde, ist der t.isAlive-Test erfolgreich und es wird kein Fehler ausgegeben. * Die Funktion f ist für alle Zwecke eine while (true) -Schleife, die in jeder Iteration nach dem Interrupt sucht. Außerdem benötigt jede Iteration wesentlich weniger Zeit als die Zuweisungsvariable zur Verfügung stellt. * Die Ausnahme gefangen ist diejenige, die ich werfe. – user108088

0

Haben Sie verschachtelte Überprüfungen von Thread.interrupted()? Diese Methode löscht das unterbrochene Flag, sodass der zweite Aufruf false zurückgibt. Sie könnten stattdessen isInterrupted() verwenden.