【多线程】java停止线程小结          返回主页

最近在做新闻爬虫的后台控制逻辑时,想要通过对前端传输的参数的解析达到对爬取逻辑的控制。

比如:前台通过单选框传来on或者off,在后台解析之后决定开启爬虫逻辑还是关闭爬虫逻辑。达到人为可控的目的。

当时想到的方式是操纵后端servlet的生存周期,调用其destory()方法结束其生命周期达到关闭的目的,但是这样做有弊端, 一旦调用destroy,整个servlet将从容器中释放,无法达到灵活加载的目的。

因此想到介入Thread生命周期,通过调用Thread内置回调方法达到目的。

这其中有两个方法比较重要,分别是Stop()interrupt()。两者都能达到线程的停止的目的。但是方式不同。

Stop()

jdk文档这样解释:

Deprecated. This method is inherently unsafe. Stopping a thread with Thread.

也就是说,该方法已经过时,且该方法是不安全的,是一种暴力的停止方案。强制对一个线程进行停止可能使得一些请理性工作得不到完成。 另一个情况就是对锁定的对象进行了“解锁”,导致数据得不到同步处理。出现数据不一致的情况。

interrupt()

因此使用了interrupt()方法。

jdk文档这样解释:

Interrupts this thread.
Unless the current thread is interrupting itself, which is always permitted, the checkAccess method of this thread is invoked, which may cause a SecurityException to be thrown.

使用该方法不会马上停止运行中的线程,它会在当前线程中打一个停止的标记,加入判断逻辑后就可以完成线程的停止。

代码示例

MyThread.java

public class MyThread extends Thread {

    @Override
    public void run() {
        super.run();
        try {
            for (int i = 0; i < 500000; i++) {
                if (this.interrupted()) {
                    System.out.println("已经停止");
                    throw new InterruptedException();
                }
                System.out.println("i=" + (i + 1));
            }
            System.out.println("还有代码所以劳资就继续运行");
        } catch (Exception e) {
            System.out.println("catch块执行了");
        }

    }
}

代码解释:这里定义一个类MyThread继承Thread类,实现run()方法。 在方法内部创建一个判断逻辑,在for()循环内部判断一下线程是否是停止状态,如果是的话就显式抛出异常,使得线程停止。否则继续运行。

Run.java

public class Run {

    public static void main(String[] args) {
        try {
            MyThread thread = new MyThread();
            thread.start();
            Thread.sleep(1000);
            System.out.println("是否停止1" + thread.isInterrupted());
            System.out.println("是否停止2" + thread.isInterrupted());
            thread.interrupt();
        } catch (Exception e) {
            System.out.println("main catch");
            e.printStackTrace();
        }
        System.out.println("end");
    }
}

代码解释:主方法,开启自定义线程类,调用其interrupt()方法,添加标记。使得线程在内部进行判断,如果条件成立,即this.interrupted()为true,则停止运行回到主线程。

运行结果

.....
i=144731
i=144732
是否停止2false
i=144733
i=144734
i=144735
i=144736
i=144737
i=144738
i=144739
end
已经停止
catch块执行了

小结

使用Thread内置的interrupt()并结合异常抛出能够较为安全的结束一个线程的运行。 虽然stop()也能够达到结束线程的目的,但是这种做法过于暴力。不推荐使用。