如何停止JAVA线程(转载)

来源:互联网 发布:淘宝外卖不能分口袋吗 编辑:程序博客网 时间:2024/05/17 01:07

如何停止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(InterruptedException ex) {/*ignore*/}            threadToInterrupt.interrupt();        }    }}

这里还需要注意一点,当线程处于写文件的状态时,调用interrupt()不会中断线程。

参考资料

How to Stop a Thread or a Task

Why are Thread.stop, Thread.suspend and Thread.resume Deprecated?

Java Threads, Third Edition O'Reilly

原创粉丝点击