• [转]JAVA线程停止的方法


       有三种方法可以使终止线程。 

        1.  使用退出标志,使线程正常退出,也就是当run方法完成后线程终止。 

        2.  使用stop方法强行终止线程(这个方法不推荐使用,因为stop和suspend、resume一样,也可能发生不可预料的结果)。 已废弃

        3.  使用interrupt方法中断线程。 

    如何停止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.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()不会中断线程。

    参考资料

    How to Stop a Thread or a Task

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

  • 相关阅读:
    c++ stringstream
    c语言中字符串数组初始化的一点总结&& c++访问控制的三种方式
    Leetcode 2. Add Two Numbers(medium)
    面试题---反转一个字符串
    编程题---在数组中取一个位置,让这个位置之前的数的和与之后的和的差绝对值最小
    美团面试准备
    Leetcode 101. Symmetric Tree(easy)
    Leetcode 665. Non-decreasing Array(Easy)
    617. Merge Two Binary Trees(Easy)
    423. Reconstruct Original Digits from English(Medium)
  • 原文地址:https://www.cnblogs.com/myPersonalTailor/p/4206917.html
Copyright © 2020-2023  润新知