• 如何停止JAVA线程


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


     




  • 相关阅读:
    ssh代理转发
    了解ssh代理:ssh-agent
    ssh使用密钥进行认证
    拾遗之”三元运算”与”打印奇偶行”
    MySQL 8.0二进制包安装
    awk内置函数
    awk数组详解
    awk动作总结之二
    awk动作总结之一
    [shell]批量抽取文件并重命名
  • 原文地址:https://www.cnblogs.com/miraclespace/p/3958245.html
Copyright © 2020-2023  润新知