Wie tötest du einen Thread in Java?

374

Wie tötest du einen java.lang.Threadin Java?

Flybywire
quelle
2
bis jetzt kann man keinen Faden töten; weil destroy () aufgrund von
Deadlock
1
Ich bevorzuge die Antwort ExecutorStatusauf diese Frage: stackoverflow.com/questions/2275443/how-to-timeout-a-thread
Kirby
9
@loungerdork "Ich denke, Java sollte eine sichere Stop / Destroy-Methode für außer Kontrolle geratene Threads implementieren, über die Sie keine Kontrolle haben, trotz der Vorbehalte, Sperren und andere Fallstricke zu verlieren." Sie möchten also einen unsicheren Thread-Stop. Ich denke du hast schon einen.
DJClayworth
4
Es ist erstaunlich, welche Art von Fragen 2009 212 positive Stimmen erhalten würden. Dies würde heute sofort zerstört werden.
Jonathon Reinhart
7
@ JonathonReinhart: Warum ist das so? Es scheint auch heutzutage eine legitime Frage zu sein. Vielleicht kennen Sie die Frustration nicht, die es verursacht, wenn Sie außer Kontrolle geratene Threads haben und nur veraltete Funktionen verwenden können, um dies irgendwie zu handhaben?
TFuto

Antworten:

189

In diesem Thread von Sun erfahren Sie, warum sie veraltet sindThread.stop() . Es wird detailliert beschrieben, warum dies eine schlechte Methode war und was getan werden sollte, um Threads im Allgemeinen sicher zu stoppen.

Sie empfehlen, eine gemeinsam genutzte Variable als Flag zu verwenden, die den Hintergrundthread zum Stoppen auffordert. Diese Variable kann dann von einem anderen Objekt festgelegt werden, das die Beendigung des Threads anfordert.

JaredPar
quelle
1
Wenn Sie überprüfen, ob der Thread, den Sie unterbrochen haben, isAlive () ist, werden Sie true zurückgeben und weiterhin zu Ihrer aktuellen ThreadGroup [] hinzugefügt. Dies können Sie mit Thread.currentThread.getThreadGroup (). list () sehen. Es werden alle Threads gedruckt, die es hat, und Sie werden mehrere Instanzen Ihres Threads sehen, wenn Sie Ihren Fluss wiederholen.
AZ_
3
Wenn Sie auf einem PC sind, ist es kein Problem, aber wenn Sie eine Software für Handys entwickeln (Android habe ich erlebt), dann erhalten Sie OutOfMemoryError
AZ_
2
Es kann / sollte beachtet werden, dass die Variable flüchtig sein muss (oder der Zugriff auf die Variable muss synchronisiert sein muss), um eine schnelle Kommunikation der Stoppanforderung über das Flag sicherzustellen, wie in der Empfehlung angegeben.
Mtsz
2
Dieser Link wurde zu diesem Zeitpunkt getötet. Ich konnte es jedoch auf archive.org finden: web.archive.org/web/20090202093154/http://java.sun.com/j2se/…
Jay Taylor
2
Ich benutze Methode getConnection()von java.sql.DriverManager. Wenn der Verbindungsversuch zu lange dauert, versuche ich, den entsprechenden Thread durch Aufrufen zu beenden, Thread.interrupt()aber er beeinflusst den Thread überhaupt nicht. Das Thread.stop()funktioniert jedoch, obwohl Orakel sagt, dass es nicht funktionieren sollte, wenn interrupt()nicht. Ich frage mich, wie es funktioniert und vermeide es, veraltete Methoden zu verwenden.
Danny Lo
129

Im Allgemeinen tun Sie nicht ..

Sie bitten es, alles, was es tut, mit Thread.interrupt () zu unterbrechen (Javadoc-Link)

Eine gute Erklärung, warum hier im Javadoc (Java Technote Link)

Fredrik
quelle
@Fredrik Was passiert mit dem Thread-Kontext, wenn die interrupt()Methode aufgerufen wird? Die Hauptfrage bezieht sich auf die Protokollgenerierung für jeden neuen Thread.
ABcDexter
3
@ABcDexter Der springende Punkt ist, dass Interrupt nichts unterbricht, sondern nur dem Code im Thread (oder dem vom Thread aufgerufenen Code) signalisiert, dass jemand ihn gebeten hat, alles zu unterbrechen, was er tut. Der Thread soll dann die Verarbeitung stoppen und zurückkehren, genau wie wenn er das getan hätte, was er sollte (und zu diesem Zeitpunkt wird der Thread-Kontext wahrscheinlich auch verworfen). OTOH, hätten Sie den Thread wirklich gewaltsam gestoppt, wäre Ihre Frage wirklich gut und die Antwort undefiniert.
Fredrik
64

In Java werden Threads nicht getötet, aber das Stoppen eines Threads erfolgt auf kooperative Weise . Der Thread wird zum Beenden aufgefordert und der Thread kann dann ordnungsgemäß heruntergefahren werden.

Oft wird ein volatile booleanFeld verwendet, das der Thread regelmäßig überprüft und beendet, wenn er auf den entsprechenden Wert gesetzt wird.

Ich würde a nicht verwenden boolean, um zu überprüfen, ob der Thread beendet werden soll . Wenn Sie volatileals Feldmodifikator verwenden, funktioniert dies zuverlässig. Wenn Ihr Code jedoch komplexer wird und stattdessen andere Blockierungsmethoden innerhalb der whileSchleife verwendet, kann es vorkommen, dass Ihr Code überhaupt nicht beendet wird oder zumindest länger dauert als Sie könnte wollen.

Bestimmte blockierende Bibliotheksmethoden unterstützen die Unterbrechung.

Jeder Thread hat bereits einen Status eines unterbrochenen Booleschen Flags, den Sie verwenden sollten. Es kann folgendermaßen implementiert werden:

public void run() {
   try {
      while (!interrupted()) {
         // ...
      }
   } catch (InterruptedException consumed)
      /* Allow thread to exit */
   }
}

public void cancel() { interrupt(); }

Quellcode aus Java Concurrency in der Praxis angepasst . Da die cancel()Methode öffentlich ist, können Sie einen anderen Thread diese Methode wie gewünscht aufrufen lassen.

Konrad Reiche
quelle
Und was tun, wenn Sie nicht vertrauenswürdigen Code als Plugin oder Skript ausführen? Java hat eine Sandbox für nicht vertrauenswürdigen Code eingebettet. Und dieser Sandkasten ist nutzlos, er ermöglicht es, ohne gewaltsamen Stopp zu arbeiten. Stellen Sie sich vor, Sie schreiben einen Browser auf Java. Die Fähigkeit, ein beliebiges Seitenskript zu töten, ist von unschätzbarem Wert.
Ayvango
@ayvango Dann müssen Sie dieses Skript in Ihrer eigenen Sandbox ausführen. Die Java-Sandbox schützt den Computer vor der Anwendung und nicht Teile der Anwendung voneinander.
David Schwartz
@ DavidSchwartz meinst du, ich sollte nur eine andere Plattform als Java verwenden?
Ayvango
@ayvango Sie können die Java-Sandbox weiterhin verwenden, um den Computer vor Ihrer Anwendung zu schützen. Wenn Sie jedoch Teile Ihrer Anwendung vor anderen Teilen Ihrer Anwendung schützen möchten, müssen Sie ein Tool auswählen, das dies ermöglicht.
David Schwartz
@DavidSchwartz ASFAIK Solche Tools könnten nicht existieren, wenn sie auf Plattformebene nicht unterstützt werden. Aber natürlich könnte die Aufgabe mit einer vollständig interpretierten Skript-Engine gelöst werden. Es könnte Reduzierungen zählen, wie es erlangt, und andere Dinge tun.
Ayvango
20

Eine Möglichkeit besteht darin, eine Klassenvariable festzulegen und als Sentinel zu verwenden.

Class Outer {
    public static volatile flag = true;

    Outer() {
        new Test().start();
    }
    class Test extends Thread {

        public void run() {
            while (Outer.flag) {
                //do stuff here
            }
        }
    }

}

Setzen Sie eine externe Klassenvariable, dh flag = true im obigen Beispiel. Setzen Sie es auf false, um den Thread zu "töten".

karim79
quelle
2
Nur als Nebenhinweis: Eine Variable als Flag funktioniert nur, wenn der Thread ausgeführt wird und nicht steckt. Thread.interrupt () sollte den Thread von den meisten Wartebedingungen befreien (warten, schlafen, Netzwerk lesen usw.). Daher sollten Sie niemals die InterruptedException abfangen, damit dies funktioniert.
ReneS
12
Das ist nicht zuverlässig; Machen Sie "Flag", volatileum sicherzustellen, dass es überall richtig funktioniert. Die innere Klasse ist nicht statisch, daher sollte das Flag eine Instanzvariable sein. Das Flag sollte in einer Accessor-Methode gelöscht werden, damit andere Operationen (wie Interrupt) ausgeführt werden können. Der Name "flag" ist nicht beschreibend.
Erickson
2
Ich bekomme das "while" -Ding in der Ausführungsmethode nicht. Bedeutet dies nicht, dass alles, was in der Ausführungsmethode geschrieben ist, wiederholt wird? Dies ist nicht etwas, was wir wollten, dass der Thread in erster Linie tun sollte :(
2
+1 tun, während (! Thread.currentThread (). IsInteruppted ()) bevorzugt wird
Toby
2
Beide Fälle schlagen fehl, wenn Sie beispielsweise einen externen Prozess innerhalb des while {// open ext-Prozesses} öffnen und dieser Prozess hängen bleibt. Jetzt wird weder der Thread unterbrochen noch das Ende erreicht, um Ihren Booleschen Zustand zu überprüfen, und Sie sind es links hängen lassen ... versuchen Sie es mit z. B. Starten Sie eine Python-Konsole mit java.exec und versuchen Sie, das Steuerelement zurückzugewinnen, ohne exit zu schreiben, und prüfen Sie, ob es eine Möglichkeit gibt, diesen Prozess zu beenden und auszusteigen. Es gibt keine Möglichkeit dazu Raus aus einer solchen Situation ...
Space Rocker
11

Es gibt eine Möglichkeit, wie Sie es tun können. Aber wenn Sie es verwenden mussten, sind Sie entweder ein schlechter Programmierer oder Sie verwenden einen Code, der von schlechten Programmierern geschrieben wurde. Sie sollten also darüber nachdenken, nicht mehr ein schlechter Programmierer zu sein oder diesen schlechten Code nicht mehr zu verwenden. Diese Lösung ist nur für Situationen geeignet, in denen es keinen anderen Weg gibt.

Thread f = <A thread to be stopped>
Method m = Thread.class.getDeclaredMethod( "stop0" , new Class[]{Object.class} );
m.setAccessible( true );
m.invoke( f , new ThreadDeath() );
VadimPlatonov
quelle
2
Es gibt überhaupt keine Gründe dafür, da es immer noch möglich ist, die Öffentlichkeit anzurufen, Thread.stopselbst wenn sie veraltet ist.
Lii
1
@Lii Thread.stopmacht dasselbe, überprüft aber auch den Zugriff und die Berechtigungen. Die Verwendung Thread.stopist ziemlich offensichtlich, und ich erinnere mich nicht an den Grund, warum ich Thread.stop0stattdessen verwendet habe. Vielleicht Thread.stophat es für meinen Sonderfall nicht funktioniert (Weblogic auf Java 6). Oder vielleicht, weil Thread.stopes veraltet ist und Warnung verursacht.
VadimPlatonov
1
In meinem Szenario war dies die einzige Möglichkeit, einen endlos laufenden Thread zu stoppen. Aus irgendeinem Grund hat .stop () den Thread nicht gestoppt, aber stop0 () hat
fiffy
10

Ich möchte einige Beobachtungen hinzufügen, die auf den gesammelten Kommentaren basieren.

  1. Thread.stop() stoppt einen Thread, wenn der Sicherheitsmanager dies zulässt.
  2. Thread.stop()ist gefährlich. Wenn Sie jedoch in einer JEE-Umgebung arbeiten und keine Kontrolle über den aufgerufenen Code haben, kann dies erforderlich sein. Siehe Warum ist Thread.stop veraltet?
  3. Sie sollten niemals aufhören, einen Container-Worker-Thread zu stoppen. Wenn Sie Code ausführen möchten, der zum Hängen neigt, starten Sie (vorsichtig) einen neuen Daemon-Thread und überwachen Sie ihn. Beenden Sie ihn gegebenenfalls.
  4. stop()erzeugt einen neuen ThreadDeathErrorFehler auf dem Aufruf - Thread und dann diese Fehler auf das wirft Zielgewinde. Daher ist die Stapelverfolgung im Allgemeinen wertlos.
  5. stop()Überprüft in JRE 6 den Sicherheitsmanager und ruft stop1()diese Anrufe dann auf stop0(). stop0()ist nativer Code.
  6. Ab Java 13 Thread.stop()wurde (noch) nicht entfernt, aber Thread.stop(Throwable)in Java 11 entfernt. ( Mailingliste , JDK-8204243 )
Steve11235
quelle
8

Ich würde dafür stimmen Thread.stop().

Zum Beispiel haben Sie einen lang anhaltenden Betrieb (wie eine Netzwerkanforderung). Angeblich warten Sie auf eine Antwort, aber es kann einige Zeit dauern, bis der Benutzer zu einer anderen Benutzeroberfläche navigiert. Dieser wartende Thread ist jetzt a) nutzlos b) potenzielles Problem, da er, wenn er ein Ergebnis erhält, völlig nutzlos ist und Rückrufe auslöst, die zu einer Reihe von Fehlern führen können.

All dies und er kann eine Antwortverarbeitung durchführen, die CPU-intensiv sein kann. Und Sie als Entwickler können es nicht einmal stoppen, weil Sie nicht den if (Thread.currentThread().isInterrupted())gesamten Code mit Zeilen versehen können.

Die Unfähigkeit, einen Thread gewaltsam zu stoppen, ist also seltsam.

Anfet
quelle
Wenn der Netzwerkbetrieb bereits sicher abgebrochen werden kann, unterbrechen Sie einfach den Thread. Wenn der Netzwerkbetrieb nicht sicher abgebrochen werden kann, können Sie Thread.stop()trotzdem nicht sicher anrufen . Sie stimmen nicht ab Thread.stop(), Sie fragen nach jeder Person, die jede Operation durchführt, die möglicherweise lange dauert, um sie sicher abzubrechen. Und das mag eine gute Idee sein, hat aber nichts mit der Implementierung zu tun Thread.stop(), um die sichere Abtreibung zu beantragen. Dafür haben wir schon interrupt.
David Schwartz
"Also die Unfähigkeit, einen Thread gewaltsam zu stoppen, ist seltsam." - ... bis Sie genau hinschauen (wie es die Java-Designer getan haben) und zu dem Schluss kommen, dass es keine technisch tragfähigen Lösungen gibt, die nicht schlechter als veraltet sind stop.
Stephen C
5

Die Frage ist eher vage. Wenn Sie gemeint haben: "Wie schreibe ich ein Programm, damit ein Thread nicht mehr ausgeführt wird, wenn ich es möchte?", Sollten verschiedene andere Antworten hilfreich sein. Aber wenn Sie meinten "Ich habe einen Notfall mit einem Server, den ich momentan nicht neu starten kann, und ich brauche nur einen bestimmten Thread, um zu sterben, was auch immer", dann brauchen Sie ein Interventionstool, das mit Überwachungstools wie z jstack.

Zu diesem Zweck habe ich jkillthread erstellt . Siehe die Gebrauchsanweisung.

Jesse Glick
quelle
Vielen Dank! Genau das, wonach ich gesucht habe!
Denis Kokorin
4

Es gibt natürlich den Fall, dass Sie einen nicht vollständig vertrauenswürdigen Code ausführen. (Ich persönlich habe dies dadurch erreicht, dass hochgeladene Skripte in meiner Java-Umgebung ausgeführt werden können. Ja, überall klingelt die Sicherheitsalarmglocke, aber dies ist Teil der Anwendung.) In diesem unglücklichen Fall sind Sie zunächst nur hoffnungsvoll, wenn Sie Skriptschreiber fragen eine Art boolesches Run / Don't-Run-Signal zu respektieren. Ihre einzige anständige Ausfallsicherheit besteht darin, die Stoppmethode für den Thread aufzurufen, wenn sie beispielsweise länger als eine Zeitüberschreitung ausgeführt wird.

Dies ist jedoch nur "anständig" und nicht absolut, da der Code den ThreadDeath-Fehler (oder eine andere Ausnahme, die Sie explizit auslösen) abfangen und ihn nicht erneut auslösen kann, wie es ein Gentleman-Thread tun soll. Das Endergebnis ist also AFAIA, es gibt keine absolute Ausfallsicherheit.

mlohbihler
quelle
AFAIK immer mehr Dienste werden hybride und verwenden verwaltete Umgebungen, um Code von Drittanbietern (Plugins, Skripte usw.) auszuführen, die sie nicht vollständig über den Code kontrollieren können. Es erscheint unangemessen, thread.stop vollständig vom Tisch zu nehmen. da für Servicetechniker ein Live-and-Serving-Zustand unendlich besser sein kann als ein Nicht-Serving-Zustand (entweder aufgrund von Hängen (das Fäden
wegnimmt
3

Es gibt keine Möglichkeit, einen Thread ordnungsgemäß zu beenden.

Sie können versuchen, den Thread zu unterbrechen. Eine übliche Strategie besteht darin, eine Giftpille zu verwenden, um dem Thread eine Nachricht zu senden, dass er sich selbst stoppen soll

public class CancelSupport {
    public static class CommandExecutor implements Runnable {
            private BlockingQueue<String> queue;
            public static final String POISON_PILL  = stopnow”;
            public CommandExecutor(BlockingQueue<String> queue) {
                    this.queue=queue;
            }
            @Override
            public void run() {
                    boolean stop=false;
                    while(!stop) {
                            try {
                                    String command=queue.take();
                                    if(POISON_PILL.equals(command)) {
                                            stop=true;
                                    } else {
                                            // do command
                                            System.out.println(command);
                                    }
                            } catch (InterruptedException e) {
                                    stop=true;
                            }
                    }
                    System.out.println(“Stopping execution”);
            }

    }

}}

BlockingQueue<String> queue=new LinkedBlockingQueue<String>();
Thread t=new Thread(new CommandExecutor(queue));
queue.put(“hello”);
queue.put(“world”);
t.start();
Thread.sleep(1000);
queue.put(“stopnow”);

http://anandsekar.github.io/cancel-support-for-threads/

Anand Rajasekar
quelle
2

Im Allgemeinen beenden, stoppen oder unterbrechen Sie einen Thread nicht (oder überprüfen, ob er unterbrochen ist ()), sondern lassen ihn auf natürliche Weise beenden.

Es ist einfach. Sie können eine beliebige Schleife zusammen mit einer (flüchtigen) booleschen Variablen in der run () -Methode verwenden, um die Aktivität des Threads zu steuern. Sie können auch vom aktiven Thread zum Haupt-Thread zurückkehren, um ihn zu stoppen.

Auf diese Weise tötest du anmutig einen Thread :).

Wojciech Domalewski
quelle
1

Versuche einer abrupten Thread-Beendigung sind bekannte schlechte Programmierpraktiken und Hinweise auf ein schlechtes Anwendungsdesign. Alle Threads in der Multithread-Anwendung haben explizit und implizit denselben Prozessstatus und müssen zusammenarbeiten, um die Konsistenz zu gewährleisten. Andernfalls ist Ihre Anwendung anfällig für Fehler, die sehr schwer zu diagnostizieren sind. Es liegt daher in der Verantwortung des Entwicklers, diese Konsistenz durch sorgfältiges und klares Anwendungsdesign sicherzustellen.

Es gibt zwei richtige Hauptlösungen für die gesteuerten Thread-Abschlüsse:

  • Verwendung des gemeinsam genutzten flüchtigen Flags
  • Verwendung der beiden Methoden Thread.interrupt () und Thread.interrupted ().

Eine gute und detaillierte Erläuterung der Probleme im Zusammenhang mit der abrupten Thread-Beendigung sowie Beispiele für falsche und richtige Lösungen für die kontrollierte Thread-Beendigung finden Sie hier:

https://www.securecoding.cert.org/confluence/display/java/THI05-J.+Do+not+use+Thread.stop%28%29+to+terminate+threads

ZarathustrA
quelle
Da Programme nicht mehr von einzelnen Entwicklern geschrieben werden, müssen häufig Threads beendet werden. Daher kann nicht als schlechte Programmierung angesehen werden. Ich kann mir Linux ohne Kill nicht vorstellen. Die Unfähigkeit, Threads zu beenden, ist ein Java-Defekt.
Pavel Niedoba
1
Genial, Mr. Right ... Was ist, wenn Sie eine Bibliothek eines Drittanbieters aufrufen müssen, über die Sie keine Kontrolle haben und die eine fehlerhafte Zeitüberschreitung aufweist und bei der Ausführung möglicherweise alle 1000 bis 2000 Mal hängen bleibt? Schlechte Programmierpraxis, oder? Sie können nicht immer auf den von Ihnen verwendeten Code zugreifen. Wie auch immer, die Operation fragt, wie man einen Thread beendet und nicht wie man seinen Fluss kontrolliert, wenn man seinen eigenen Code entwirft ...
Arturas M
Die Frage ist, was passiert, wenn Sie einen Thread beenden, dem Mutex gehört oder dem ein Speicherblock zugewiesen ist oder der ein Ereignis oder Daten generieren soll, auf die ein anderer Thread wartet? Was passiert mit dem Rest der Logik Ihrer Anwendung? Es besteht immer das Risiko, dass kleine und offensichtliche Probleme in komplexe Probleme umgewandelt werden, die schwer zu reproduzieren und zu untersuchen sind. Das Beenden des Threads ist unsicher, da Ihre Anwendung dadurch in verschiedenen inkonsistenten Zuständen verbleiben kann. Schauen Sie sich die Informationen über den Link auf cert.org an.
ZarathustrA
Wir haben einen kontrollierenden Thread, der unter bestimmten Bedingungen entscheiden kann, dass die gesamte Berechnung gerade sinnlos geworden ist. Die vielen verschiedenen Runnables, die die eigentliche Arbeit erledigen, müssen an jedem geeigneten Ort mit einer Variante von isInterrupted () bespritzt werden - wie schrecklich! Es ist so viel schöner, wenn der Controller einen ThreadDeath scheinbar aus dem Nichts aufsteigen lässt und alle synchronisierten und schließlich Blöcke sauber abwickelt. Jeder sagt, dass dies so fehleranfällig ist, aber für ziemlich unabhängige Threads verstehe ich nicht warum.
Daniel
1

Ich habe den Interrupt nicht in Android zum Laufen gebracht, also habe ich diese Methode verwendet, funktioniert perfekt:

boolean shouldCheckUpdates = true;

private void startupCheckForUpdatesEveryFewSeconds() {
    Thread t = new Thread(new CheckUpdates());
    t.start();
}

private class CheckUpdates implements Runnable{
    public void run() {
        while (shouldCheckUpdates){
            //Thread sleep 3 seconds
            System.out.println("Do your thing here");
        }
    }
}

 public void stop(){
        shouldCheckUpdates = false;
 }
Mindborg
quelle
2
Das flüchtige Schlüsselwort sollte zu shouldCheckUpdates hinzugefügt werden, falls der Compiler mit dem lokalen Thread-Speicher optimiert.
Clinux
1

"Einen Thread töten" ist nicht der richtige Ausdruck. Hier ist eine Möglichkeit, wie wir das ordnungsgemäße Beenden / Beenden des Threads auf Willen implementieren können:

Runnable, das ich verwendet habe:

class TaskThread implements Runnable {

    boolean shouldStop;

    public TaskThread(boolean shouldStop) {
        this.shouldStop = shouldStop;
    }

    @Override
    public void run() {

        System.out.println("Thread has started");

        while (!shouldStop) {
            // do something
        }

        System.out.println("Thread has ended");

    }

    public void stop() {
        shouldStop = true;
    }

}

Die auslösende Klasse:

public class ThreadStop {

    public static void main(String[] args) {

        System.out.println("Start");

        // Start the thread
        TaskThread task = new TaskThread(false);
        Thread t = new Thread(task);
        t.start();

        // Stop the thread
        task.stop();

        System.out.println("End");

    }

}
Adesh
quelle
Das flüchtige Schlüsselwort sollte zur Variable shouldStop hinzugefügt werden, falls der Compiler mit dem lokalen Thread-Speicher optimiert.
Oleksii Kyslytsyn
0

Thread.stop ist veraltet. Wie stoppen wir einen Thread in Java?

Verwenden Sie immer die Interrupt-Methode und die Zukunft, um eine Stornierung anzufordern

  1. Wenn die Task beispielsweise auf ein Interrupt-Signal reagiert, wird die Methode zum Blockieren der Warteschlange verwendet.
Callable < String > callable = new Callable < String > () {
    @Override
    public String call() throws Exception {
        String result = "";
        try {
            //assume below take method is blocked as no work is produced.
            result = queue.take();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        return result;
    }
};
Future future = executor.submit(callable);
try {
    String result = future.get(5, TimeUnit.SECONDS);
} catch (TimeoutException e) {
    logger.error("Thread timedout!");
    return "";
} finally {
    //this will call interrupt on queue which will abort the operation.
    //if it completes before time out, it has no side effects
    future.cancel(true);
}
  1. Wenn die Task nicht auf das Interrupt-Signal reagiert. Angenommen, die Task führt eine Socket-E / A aus, die nicht auf das Interrupt-Signal reagiert, und daher wird die Aufgabe bei Verwendung des obigen Ansatzes nicht abgebrochen , Thread hört weiter auf Socket. Wir können den Socket schließen oder die Methode close bei der Verbindung aufrufen, wenn sie vom Pool implementiert wird.
public interface CustomCallable < T > extends Callable < T > {
    void cancel();
    RunnableFuture < T > newTask();
}

public class CustomExecutorPool extends ThreadPoolExecutor {
    protected < T > RunnableFuture < T > newTaskFor(Callable < T > callable) {
        if (callable instanceof CancellableTask)
            return ((CancellableTask < T > ) callable).newTask();
        else
            return super.newTaskFor(callable);
    }
}

public abstract class UnblockingIOTask < T > implements CustomCallable < T > {
    public synchronized void cancel() {
        try {
            obj.close();
        } catch (IOException e) {
            logger.error("io exception", e);
        }
    }

    public RunnableFuture < T > newTask() {
        return new FutureTask < T > (this) {
            public boolean cancel(boolean mayInterruptIfRunning) {
                try {
                    this.cancel();
                } finally {
                    return super.cancel(mayInterruptIfRunning);
                }
            }

        };
    }
}
Gautam Tadigoppula
quelle