Frage

Ich habe eine Aufgabe mit Vollstreckern vorgelegt und ich brauche es nach einiger Zeit zu stoppen (zum Beispiel 5 Minuten). Ich habe versucht, wie dies zu tun:

   for (Future<?> fut : e.invokeAll(tasks, 300, TimeUnit.SECONDS)) {
         try {
             fut.get(); 
         } catch (CancellationException ex) {
             fut.cancel(true);   
             tasks.clear();
         } catch(ExecutionException ex){
             ex.printStackTrace(); //FIXME: gestita con printstack       
         }
   }

Aber ich immer einen Fehler: Ich habe ein Foto geteilt, die von den Aufgaben geändert werden muss und dann von einem Thread gelesen, und selbst wenn ich aufhören alle die Aufgabe, wenn das Timeout auftritt, erhalte ich:

Exception in thread "Thread-1" java.util.ConcurrentModificationException

Gibt es etwas falsch? Wie kann ich die Aufgaben abgegeben stoppen, die noch nach 5 Minuten arbeiten?

War es hilfreich?

Lösung

Nur weil Sie cancel() auf Future nennen, bedeutet nicht, dass die Aufgabe automatisch gestoppt. Sie haben einige Arbeit in der Aufgabe zu tun, um sicherzustellen, dass es zu stoppen:

  • Verwenden Sie cancel(true) so dass eine Unterbrechung der Aufgabe gesendet wird.
  • Handle InterruptedException. Wenn eine Funktion in Ihrer Aufgabe eine InterruptedException wirft, stellen Sie sicher, dass Sie anmutig so schnell wie möglich verlassen, auf die Ausnahme zu kontrollieren.
  • Überprüfen Sie regelmäßig Thread.currentThread().isInterrupted(), wenn die Aufgabe kontinuierliche Berechnung der Fall ist.

Zum Beispiel:

class LongTask implements Callable<Double> {
    public Double call() {

         // Sleep for a while; handle InterruptedException appropriately
         try {
             Thread.sleep(10000);
         } catch (InterruptedException ex) {
             System.out.println("Exiting gracefully!");
             return null;
         }


         // Compute for a while; check Thread.isInterrupted() periodically
         double sum = 0.0;
         for (long i = 0; i < 10000000; i++) {
             sum += 10.0
             if (Thread.currentThread().isInterrupted()) {
                 System.out.println("Exiting gracefully");
                 return null;
             }
         }

         return sum;
    } 
}

Auch, wie andere Beiträge erwähnt haben: ConcurrentModificationException können sogar geworfen werden, wenn die Thread-sichere Vector-Klasse, weil Iteratoren Sie von Vector erhalten sind nicht Thread-sicher und damit synchronisiert werden müssen. Die erweiterte for-Schleife verwendet Iteratoren, also aufgepasst:

final Vector<Double> vector = new Vector<Double>();
vector.add(1.0);
vector.add(2.0);

// Not thread safe!  If another thread modifies "vector" during the loop, then
// a ConcurrentModificationException will be thrown.
for (Double num : vector) {
    System.out.println(num);
}

// You can try this as a quick fix, but it might not be what you want:
synchronized (vector) {    // "vector" must be final
    for (Double num : vector) {
        System.out.println(num);
    }
}

Andere Tipps

Die ConcurrentModificationException von Ihrem Anruf kommen nach tasks.clear() während Exceutors über Ihre tasks Vector iteriert. Was Sie versuchen können, ist Aufruf zu tun shutdownNow() auf Ihrem ExecutorService

Der häufigste Fall für ConcurrentModificationException ist, wenn der vector zugleich geändert wird, wie es wiederholt wird. Oft wird dies in einem einzigen Thread ausgeführt werden. Sie müssen eine Sperre für die Vector für die gesamte Iteration halten (und vorsichtig, nicht Deadlock).

fut.get () ist ein blockierender Aufruf, auch nach dem Timeout, werden Sie blockieren, bis die Aufgabe erledigt ist. Wenn Sie so nahe an der 5-Minuten-Marke wie möglich stoppen wollen, müssen Sie das Interrupt-Flag überprüfen, empfehle ich nur tun Sie so die Thread.isInterrupted () Methode verwendet, die den Interrupt Zustand bewahrt. Wenn Sie nur wollen sofort stoppen und benötigen keinen Zustand zu reinigen, dann eine Ausnahme aus, die von der Zukunft gefangen werden und angegeben als ExecutionException zu Ihnen.

fut.cancel (true) tut nichts als invokeAll () -Methode dies bereits für Sie getan hat.

Wenn Sie nicht die „Aufgaben“ Collection woanders verwenden, werden Sie wahrscheinlich brauchen, um auf sie nicht nennen clear (). Dies ist nicht die Ursache des Problems sein würde, da die invokeAll () Methode mit der List von der Zeit gemacht wird Ihnen klar () aufrufen. Aber, wenn Sie eine Liste der neuen Aufgaben beginnen müssen Bildung auszuführen, empfehle ich Ihnen eine neue Liste der Aufgaben bilden, nicht eine alte Liste der neuen Aufgaben verwenden.

Leider habe ich keine Antwort für Ihr Problem. Ich sehe nicht genug Informationen hier, um es zu diagnostizieren. Nichts in der Code-Schnipsel Ihnen zur Verfügung gestellten weisen auf eine falsche (nur unnötig) Verwendung von Bibliotheksklassen / Methoden. Vielleicht, wenn Sie einen vollständigen Stack-Trace enthalten, anstelle des einen Leitungsfehler.

Setzen Sie den fut.cancel(true); in der finally-Block

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top