停止中断线程的方法

Thread.run执行完毕,线程就结束了;

Thread.stop:虽然确实可以停止一个正在运行的线程,但是这种方法是不安全的,也不被提倡;

Thread.interrupt:并不会中断一个正在运行的线程

中断线程最好的,最受推荐的方式是使用共享变量发出信号,告诉线程必须停止当前任务,而线程需要周期性地检查这一变量,然后有秩序地终止任务(没有用到interrupt方法,共享变量是volatile类型或将对它的一切访问封装到同步块/方法中);

但是,当线程因等待某些事件发生而被阻塞,便不能核查共享变量,也就不能停止,所以需要某种机制使得线程更早地退出被阻塞的状态。
Thread.interrupt实际完成的是,在线程受到阻塞时抛出一个中断信号,这样线程就可以退出阻塞状态,更确切地说,如果线程被Object.wait,Thread.join和Thread.sleep三种方法之一阻塞,就会接到一个InterruptedException,从而提早结束阻塞状态。

因此,如果线程被上述几种方式阻塞,正确的停止方式是:先设置共享变量,再调用interrupt方法,如果线程没有被阻塞,这时interrupt将不起作用;否则,线程将得到异常,并逃离阻塞状态。
代码示例:
public class Test {
    
    public static void main(String[] args) throws InterruptedException {
        MyThread t = new MyThread();
        System.out.println("Start thread...");
        t.start();
        Thread.sleep(3000);
        System.out.println("Ask thread to stop...");
        t.stop = true;
        t.interrupt();
        Thread.sleep(3000);
        System.out.println("stop...");
    }
    
    static class MyThread extends Thread {
        
        static volatile boolean stop = false;
        public void run() {
            while(!stop) {
                try {
                    Thread.sleep(1000);
                    System.out.println("MyThread running...");
                } catch (InterruptedException e) {
                    System.out.println("MyThread interrupted...");
                }
            }
            System.out.println("MyThread exist under request...");
        }
    }
}


运行结果:
Start thread...
MyThread running...
MyThread running...
Ask thread to stop...
MyThread interrupted...
MyThread exist under request...
stop...

中断I/O操作:
I/O操作可以阻塞线程一段相当长的时间,特别是牵扯到网络应用时。例如,服务器可能要等待一个请求(request),又或者,一个网络应用程序可能要等待 远端主机的响应。
如果正在使用通道(channels,在Java4中引入的I/O API),那么被阻塞的线程将收到一个ClosedByInterruptException异常,如果情况是这样,代码逻辑和上面的代码是相同的,只不过异常不同;

但是,如果使用的是Java 1.0之前的传统I/O,Thread.interrupt将不起作用,因为线程将不会退出被阻塞的状态。此时,Java平台的解决方案为:调用阻塞该线程的套接字Socket的close方法,在这种情形下,如果线程被I/O操作阻塞,该线程将接收一个SocketException,这与interrupt方法引起的InterruptedException异常非常相似。唯一要说明的是,必须存在socket的引用,只有这样close方法才能被调用,这意味着socket对象必须被共享。

猜你喜欢

转载自www.cnblogs.com/yuanfei1110111/p/10176198.html