最近在做新闻爬虫的后台控制逻辑时,想要通过对前端传输的参数的解析达到对爬取逻辑的控制。
比如:前台通过单选框传来on或者off,在后台解析之后决定开启爬虫逻辑还是关闭爬虫逻辑。达到人为可控的目的。
当时想到的方式是操纵后端servlet的生存周期,调用其destory()方法结束其生命周期达到关闭的目的,但是这样做有弊端, 一旦调用destroy,整个servlet将从容器中释放,无法达到灵活加载的目的。
因此想到介入Thread生命周期,通过调用Thread内置回调方法达到目的。
这其中有两个方法比较重要,分别是Stop(),interrupt()。两者都能达到线程的停止的目的。但是方式不同。
jdk文档这样解释:
Deprecated. This method is inherently unsafe. Stopping a thread with Thread.
也就是说,该方法已经过时,且该方法是不安全的,是一种暴力的停止方案。强制对一个线程进行停止可能使得一些请理性工作得不到完成。 另一个情况就是对锁定的对象进行了“解锁”,导致数据得不到同步处理。出现数据不一致的情况。
因此使用了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.
使用该方法不会马上停止运行中的线程,它会在当前线程中打一个停止的标记,加入判断逻辑后就可以完成线程的停止。
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()循环内部判断一下线程是否是停止状态,如果是的话就显式抛出异常,使得线程停止。否则继续运行。
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()也能够达到结束线程的目的,但是这种做法过于暴力。不推荐使用。