首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

如何正確停止 Java 線程

     編輯:Java 相關知識

簡介

Java 多線程編程中,java.lang.Thread 類包含 start()、stop()、stop(Throwable)、suspend()、destroy()、resume() 等方法。通過這些方法可方便操作線程,但只有 start() 方法被保留,其餘均被棄用。

Sun 文章《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 關鍵字原因,請查看 Java 語言規範。

線程處於非運行狀態時

線程處於以下狀況屬非運行狀態:

  • 調用 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.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 接口。實現此接口的類可在阻塞時拋出 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.)");
            (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());
        }
    }
    public static class TimeOut extends Thread {
        int sleepTime = 10000;
        Thread threadToInterrupt = null;
        public TimeOut() {
            threadToInterrupt = Thread.currentThread();
            setDaemon(true);
        }
        public void run() {
            try { sleep(10000); }
            catch(InterruptedException ex) {}
            threadToInterrupt.interrupt();
        }
    }
}

注意:線程處於寫文件狀態時,調用 interrupt() 不會中斷線程。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved