2010-12-13 11 views
1

Ich habe gerade aus Suns Dokument gelernt, dass beim Aufruf der thread.stop() -Methode die run() -Methode beendet wird, wenn der ThreadDeath-Fehler ausgelöst wird, und auch alle Sperren dieses Threads freigibt, wie kann man es beweisen?Warum thread.stop() nicht funktioniert?

versuchte ich mein Testprogramm, unten gezeigt:

public static void main(String[] args) { 
    final Object lock = new Object(); 
    try { 
    Thread t = new Thread() { 
    public synchronized void run() { 
    try { 
     synchronized (lock) { 
     long start = System.currentTimeMillis(); 
     for (int i = 0; i < 10000; i++) 
     System.out.println("runing.." + i); 
     System.out 
     .println((System.currentTimeMillis() - start)/1000); 
     } 

    } catch (Throwable ex) { 
     System.out.println("Caught in run: " + ex); 
     ex.printStackTrace(); 
    } 
    } 
    }; 

    t.start(); 
    // Give t time to get going... 
    Thread.sleep(100); 
    t.stop(); // EXPECT COMPILER WARNING 
    } catch (Throwable t) { 
    System.out.println("Caught in main: " + t); 
    t.printStackTrace(); 
    } 

} 

Nur wenn ich eine Wartezeit setzen() in der Methode run(), dann kann ich den Thread Fehler fangen, weiß jemand die Details, wie jvm handle stop()?

public static void main(String[] args) { 
    final Object lock = new Object(); 
    try { 
    Thread t = new Thread() { 
    public synchronized void run() { 
    try { 
     synchronized (lock) { 
     wait(); 
     long start = System.currentTimeMillis(); 
     for (int i = 0; i < 10000; i++) 
     System.out.println("runing.." + i); 
     System.out 
     .println((System.currentTimeMillis() - start)/1000); 

     } 

    } catch (Throwable ex) { 
     System.out.println("Caught in run: " + ex); 
     ex.printStackTrace(); 
    } 
    } 
    }; 

    t.start(); 
    // Give t time to get going... 
    Thread.sleep(100); 
    t.stop(); // EXPECT COMPILER WARNING 
    } catch (Throwable t) { 
    System.out.println("Caught in main: " + t); 
    t.printStackTrace(); 
    } 

} 

Antwort

2

Das liegt daran, dass der Thread ausgeführt wird, bevor Ihr aktueller Thread aus dem Ruhezustand kommt und den t.stop aufruft.

4

Ich glaube nicht, dass ich besser als Sun erklären kann.

Hier sind die Zitate aus offiziellen Javadoc:

Veraltet. Diese Methode ist von Natur aus unsicher. Wenn ein Thread mit Thread.stop angehalten wird, werden alle überwachten Monitore entsperrt (als natürliche Folge der ungeprüften ThreadDeath-Ausnahme, die den Stack weitergibt). Wenn eines der zuvor von diesen Monitoren geschützten Objekte einen inkonsistenten Zustand aufweist, werden die beschädigten Objekte für andere Threads sichtbar, was zu willkürlichem Verhalten führen kann. Viele Verwendungen von stop sollten durch Code ersetzt werden, der einfach eine Variable ändert, um anzuzeigen, dass der Zielthread nicht mehr ausgeführt werden sollte. Der Zielthread sollte diese Variable regelmäßig überprüfen und ordnungsgemäß von seiner Ausführungsmethode zurückkehren, wenn die Variable angibt, dass sie nicht mehr ausgeführt werden soll. Wenn das Ziel threa link text d lange Zeit wartet (z. B. bei einer Bedingungsvariablen), sollte die Interrupt-Methode verwendet werden, um die Wartezeit zu unterbrechen. Weitere Informationen finden Sie unter Warum sind Thread.stop, Thread.suspend und Thread.resume veraltet ?.

Siehe hier: http://download.oracle.com/javase/1.4.2/docs/api/java/lang/Thread.html

5

Die einfache Antwort ist, dass die JVM keine zuverlässige Möglichkeit, ein Gewinde zu stoppen. Um einen Thread zu stoppen oder zu unterbrechen, muss der Zielthread zusammenarbeiten, indem er in einen unterbrechbaren Zustand eintritt, z. B. sleep() oder wait().

Die Thread.stop() -Methode wurde (unter anderem) aus diesem Grund nicht weiter unterstützt. Weitere Informationen finden Sie unter http://download.oracle.com/javase/1.4.2/docs/guide/misc/threadPrimitiveDeprecation.html.

0

Der Thread.stop() stoppt einen Thread nicht. Stattdessen ruft sie Thread.stop (new ThreadDeath()) auf, wodurch der Thread diesen Fehler auslöst, der standardmäßig ignoriert wird. Wenn Sie also ein anderes Throwable werfen, wird es von uncaughtException in System.err ausgegeben. Von ThreadGroup

public void uncaughtException(Thread t, Throwable e) { 
if (parent != null) { 
    parent.uncaughtException(t, e); 
} else { 
     Thread.UncaughtExceptionHandler ueh = 
      Thread.getDefaultUncaughtExceptionHandler(); 
     if (ueh != null) { 
      ueh.uncaughtException(t, e); 
     } else if (!(e instanceof ThreadDeath)) { 
    System.err.print("Exception in thread \"" 
      + t.getName() + "\" "); 
      e.printStackTrace(System.err); 
     } 
    } 
} 

Es gibt nichts besonderes/magische über diesen Fehler. Dein Thread wird sich auf die gleiche Weise auflösen, wenn du neue ThreadDeath() werfen würdest. Zum Vergleich, versuchen Sie

-1

Die echte Antwort ist, dass die Stopp-Methode der Klasse Thread ruft die private stop1-Methode, die synchronisiert ist. Da die Implementierung der Ausführungsmethode des Threads ebenfalls synchronisiert wird, kann die stop1-Methode erst nach dem Beenden der run-Methode eingegeben werden.

+0

unwahr, die Synchronisierung. ist auf einem beliebigen Sperrobjekt. Der wahre Grund - der Thread wird normal beendet. – bestsss

0

Die Erklärungen zu Thread.stop sind ziemlich genau richtig.Der richtige Weg, eine kooperative runnable zu bauen, ist wie folgt:

public class MyRunnable implements Runnable { 
    private volatile boolean stopped = false; 
    public void stop() { 
     stopped = true; 
    } 

    public void run() { 
     // do stuff 
     if (stopped) { 
     // cleanup and return; 
     } 

     // do more stuff 

     if (stopped) { 
      // cleanup and return; 
     } 
    } 
} 

Runnable r = new MyRunnable(); 
Thread t = new Thread(r); 
t.start(); 
r.stop(); 
t.join(); // if you want to wait for it to die. 

ODER

public class MyRunnable implements Runnable { 
    public void run() { 
     // do stuff 
     if (Thread.currentThread().isInterrupted()) { 
     // cleanup and return; 
     } 

     // do more stuff 

     if (Thread.currentThread().isInterrupted()) { 
      // cleanup and return; 
     } 
    } 
} 

Runnable r = new MyRunnable(); 
Thread t = new Thread(r); 
t.start(); 
t.interrupt(); 
t.join(); // if you want to wait for it to die. 

Beachten Sie, dass in jedem Fall Sie strategische Haltepunkte in Ihrem Code haben, wo Sie überprüfen, ob Sie sehen sollte die Verarbeitung fortsetzen. Der zweite Ansatz hat den Vorteil, dass unterbrechungssensitive Operationen wie Thread.sleep und java.nio-basierte E/A-Operationen sofort unterbrochen werden können und nicht auf Ihren Haltepunkt warten müssen. Stattdessen würden sie sofort eine InterruptedException auslösen (oder im Fall von NIO eine ClosedByInterruptException). Beachten Sie, dass die standardmäßige java.io-basierte I/O nicht interruptfähig ist und Sie auf einen Ihrer codierten Stopppunkte warten müssen.