Java 關閉Thread詳解__Java

來源:互聯網
上載者:User

轉至:http://blog.csdn.net/anhuidelinger/article/details/11746365


   終止線程的三種方法 

    有三種方法可以使終止線程。 

    1.  使用退出標誌,使線程正常退出,也就是當run方法完成後線程終止。 

    2.  使用stop方法強行終止線程(這個方法不推薦使用,因為stop和suspend、resume一樣,也可能發生不可預料的結果)。 

    3.  使用interrupt方法中斷線程。 
1. 使用退出標誌終止線程 

    當run方法執行完後,線程就會退出。但有時run方法是永遠不會結束的。如在服務端程式中使用線程進行監聽用戶端請求,或是其他的需要迴圈處理的任務。在這種情況下,一般是將這些任務放在一個迴圈中,如while迴圈。如果想讓迴圈永遠運行下去,可以使用while(true){……}來處理。但要想使while迴圈在某一特定條件下退出,最直接的方法就是設一個boolean類型的標誌,並通過設定這個標誌為true或false來控制while迴圈是否退出。下面給出了一個利用退出標誌終止線程的例子。 

package chapter2; 

public class ThreadFlag extends Thread 
{ 
    public volatile boolean exit = false; 

    public void run() 
    { 
        while (!exit); 
    } 
    public static void main(String[] args) throws Exception 
    { 
        ThreadFlag thread = new ThreadFlag(); 
        thread.start(); 
        sleep(5000); // 主線程延遲5秒 
        thread.exit = true;  // 終止線程thread 
        thread.join(); 
        System.out.println("線程退出!"); 
    } 
} 


    在上面代碼中定義了一個退出標誌exit,當exit為true時,while迴圈退出,exit的預設值為false.在定義exit時,使用了一個Java關鍵字volatile,這個關鍵字的目的是使exit同步,也就是說在同一時刻只能由一個線程來修改exit的值, 

    2. 使用stop方法終止線程 

    使用stop方法可以強行終止正在運行或掛起的線程。我們可以使用如下的代碼來終止線程: 

thread.stop(); 


    雖然使用上面的代碼可以終止線程,但使用stop方法是很危險的,就象突然關閉電腦電源,而不是按正常程式關機一樣,可能會產生不可預料的結果,因此,並不推薦使用stop方法來終止線程。 

    3. 使用interrupt方法終止線程 

    使用interrupt方法來終端線程可分為兩種情況: 

    (1)線程處於阻塞狀態,如使用了sleep方法。 

    (2)使用while(。isInterrupted()){……}來判斷線程是否被中斷。 

    在第一種情況下使用interrupt方法,sleep方法將拋出一個InterruptedException例外,而在第二種情況下線程將直接退出。下面的代碼示範了在第一種情況下使用interrupt方法。 

package chapter2; 

public class ThreadInterrupt extends Thread 
{ 
    public void run() 
    { 
        try 
        { 
            sleep(50000);  // 延遲50秒 
        } 
        catch (InterruptedException e) 
        { 
            System.out.println(e.getMessage()); 
        } 
    } 
    public static void main(String[] args) throws Exception 
    { 
        Thread thread = new ThreadInterrupt(); 
        thread.start(); 
        System.out.println("在50秒之內按任意鍵中斷線程!"); 
        System.in.read(); 
        thread.interrupt(); 
        thread.join(); 
        System.out.println("線程已經退出!"); 
    } 
} 


    上面代碼的運行結果如下: 

    在50秒之內按任意鍵中斷線程! 

    sleep interrupted 
    線程已經退出! 


    在調用interrupt方法後, sleep方法拋出異常,然後輸出錯誤資訊:sleep interrupted. 

    注意:在Thread類中有兩個方法可以判斷線程是否通過interrupt方法被終止。一個是靜態方法interrupted(),一個是非靜態方法isInterrupted(),這兩個方法的區別是interrupted用來判斷當前線是否被中斷,而isInterrupted可以用來判斷其他線程是否被中斷。因此,while (。isInterrupted())也可以換成while (。Thread.interrupted())。 
如何停止JAVA線程

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

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

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

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

    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方法被調用。

當wait方法被調用。

當被I/O阻塞,可能是檔案或者網路等等。

當線程處於上述的狀態時,使用前面介紹的方法就不可用了。這個時候,我們可以使用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.gpcusterimport 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.gpcusterimport 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(InterruptedExcept

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.