如何中止JAVA線程


如何中止java的線程一直是一個困惱咱們開發多線程程序的一個問題。這個問題最終在Java5的java.util.concurrent中獲得了回答:使用interrupt(),讓線程在run方法中中止。 html

簡介

在Java的多線程編程中,java.lang.Thread類型包含了一些列的方法start()stop()stop(Throwable) and suspend()destroy() and resume()。經過這些方法,咱們能夠對線程進行方便的操做,可是這些方法中,只有start()方法獲得了保留。 java

在Sun公司的一篇文章《Why are Thread.stop, Thread.suspend and Thread.resume Deprecated? 》中詳細講解了捨棄這些方法的緣由。那麼,咱們究竟應該如何中止線程呢? 編程

建議使用的方法

在《Why are Thread.stop, Thread.suspend and Thread.resume Deprecated? 》中,建議使用以下的方法來中止線程: api

    private volatile Thread blinker; 
    public void stop() { 
        blinker = null
    } 
    public void run() { 
        Thread thisThread = Thread.currentThread(); 
        while (blinker == thisThread) { 
            try { 
                thisThread.sleep(interval); 
            } catch (InterruptedException e){ 
            } 
            repaint(); 
        } 
    } 安全

關於使用volatile關鍵字的緣由,請查看http://java.sun.com/docs/books/jls/second_edition/html/classes.doc.html#36930網絡

當線程處於非運行(Run)狀態

當線程處於下面的情況時,屬於非運行狀態: 多線程

  • 當sleep方法被調用。 ide

  • 當wait方法被調用。 ui

  • 當被I/O阻塞,多是文件或者網絡等等。 this

當線程處於上述的狀態時,使用前面介紹的方法就不可用了。這個時候,咱們能夠使用interrupt()來打破阻塞的狀況,如:

public void stop() {
        Thread tmpBlinker = blinker;
        blinker = null; if (tmpBlinker != null) {
           tmpBlinker.interrupt();
        }
    }

interrupt()被調用的時候,InterruptedException將被拋出,因此你能夠再run方法中捕獲這個異常,讓線程安全退出:

try {
   ....
   wait();
} catch (InterruptedException iex) { throw new RuntimeException("Interrupted",iex);
}

阻塞的I/O

當線程被I/O阻塞的時候,調用interrupt()的狀況是依賴與實際運行的平臺的。在Solaris和Linux平臺上將會拋出InterruptedIOException的異常,可是Windows上面不會有這種異常。因此,咱們處理這種問題不能依靠於平臺的實現。如:

package com.cnblogs.gpcuster import java.net.*; import java.io.*; public abstract class InterruptibleReader extends Thread { private Object lock = new Object( ); private InputStream is; private boolean done; private int buflen; protected void processData(byte[] b, int n) { } class ReaderClass extends Thread { public void run( ) { byte[] b = new byte[buflen]; while (!done) { try { int n = is.read(b, 0, buflen);
                    processData(b, n);
                } catch (IOException ioe) {
                    done = true;
                }
            } synchronized(lock) {
                lock.notify( );
            }
        }
    } public InterruptibleReader(InputStream is) { this(is, 512);
    } public InterruptibleReader(InputStream is, int len) { this.is = is;
        buflen = len;
    } public void run( ) {
        ReaderClass rc = new ReaderClass( ); synchronized(lock) {
            rc.start( ); while (!done) { try {
                    lock.wait( );
                } catch (InterruptedException ie) {
                    done = true;
                    rc.interrupt( ); try {
                        is.close( );
                    } catch (IOException ioe) {}
                }
            }
        }
    }
}

另外,咱們也能夠使用InterruptibleChannel接口。 實現了InterruptibleChannel接口的類能夠在阻塞的時候拋出ClosedByInterruptException。如:

package com.cnblogs.gpcuster import java.io.BufferedReader; import java.io.FileDescriptor; import java.io.FileInputStream; import java.io.InputStream; import java.io.InputStreamReader; import java.nio.channels.Channels; public class InterruptInput { static BufferedReader in = new BufferedReader( new InputStreamReader(
            Channels.newInputStream(
            (new FileInputStream(FileDescriptor.in)).getChannel()))); public static void main(String args[]) { try {
            System.out.println("Enter lines of input (user ctrl+Z Enter to terminate):");
            System.out.println("(Input thread will be interrupted in 10 sec.)"); // interrupt input in 10 sec (new TimeOut()).start();
            String line = null; while ((line = in.readLine()) != null) {
                System.out.println("Read line:'"+line+"'");
            }
        } catch (Exception ex) {
            System.out.println(ex.toString()); // printStackTrace(); }
    } public static class TimeOut extends Thread { int sleepTime = 10000;
        Thread threadToInterrupt = null; public TimeOut() { // interrupt thread that creates this TimeOut. threadToInterrupt = Thread.currentThread();
            setDaemon(true);
        } public void run() { try {
                sleep(10000); // wait 10 sec } catch(InterruptedException ex) {/*ignore*/}
            threadToInterrupt.interrupt();
        }
    }
}

這裏還須要注意一點,當線程處於寫文件的狀態時,調用interrupt()不會中斷線程。

相關文章
相關標籤/搜索