Skip to content

Latest commit

 

History

History
23 lines (15 loc) · 2.43 KB

File metadata and controls

23 lines (15 loc) · 2.43 KB

Stop the thread!

去年用Rhino Javascript引擎作东西的时候,遇到一个棘手的问题。就是怎么样防止输入的Javascript脚本死循环和无限递归,从而导致服务器端的奔溃。后来我们发现只有用执行时间timeout来作限制条件。很多的online的IDE也是用的这个方法。关于能不能写一个程序来检测另外一个程序是不是死循环的问题,我会再开一篇文章来讨论这个问题。

Javascript引擎是用java实现的,所以问题的本质成了怎么样在给定时间内停掉一个java线程。 用Thread.stop()? 现在还用这个方法的程序员已经不多了吧。。。不解释了,呵呵。 那么剩下的基本就两种方式了:

  1. 用一个线程间share的变量来做flag 每次被控线程作基本操作的时候,先判断flag再执行,否则结束自己的逻辑。

  2. 用线程interrupt协作机制来停线程

这里的前提条件是你的线程得要响应收到的interrupt。线程不响应interrupt或者直接吞掉InterruptException,你也没办法。

所以这两种方案的前提是:运行的线程是你自己写的逻辑,这样才能把它安全停掉。JDK里面有成熟的ExecutorService作线程池管理,但是它也是基于interrupt协作机制来试图停止线程。你线程代码不响应interrupt的话,ExecutorService也没办法。 我们产品的逻辑代码是客户写的,根本不可能有flag变量和interrupt协作机制。但是最终我们还是解决了这个问题。

这个方案是基于Rhino的实现,其实和java线程机制没关系。我们最终是利用Rhino自己的API来停止工作的。Rhino有个相当于事件侦听的接口,每执行若干指令便会调callback这个方法。我们就在这个方法里把整个Rhino返回掉。

听起来挺完美?No。。。我想说的是在现实情况下,说到停止程序,我们一般并不是想要程序立即停止工作,而是先要把手头的变量该写完整的写完整,资源该cleanup的就cleanup掉,然后退出线程。所以利用Rhino API退出的这种生硬的做法其实并不好,试想如果在调用数据库操作的时候,强制退出程序就有资源未释放的危险。在我看来这比Thread.stop()好不了多少。

结论是**任务代码一定比发出停止请求的代码更清楚如何执行清理工作,强退线程一定是不妥的。**正如Kill -9是强悍的也是危险的。