前提概要
当我们使用java脚本API运行脚本的时候,在一些我们并不知道脚本的程序逻辑
并且无法修改脚本的特殊的场景下,如果脚本中存在死循环(endless loop)
或者高资源消耗的耗时循环语句,程序运行将会占用大量的系统资源,比如说CPU、
磁盘IO等。如果脚本程序是死循环并且程序同步地执行脚本的话,那么程序将会一直阻塞下去。
解决办法
由于在这些场景下,我们无法控制脚本的程序逻辑,无法改动脚本的代码,
所以有必要对脚本的执行进行控制。在这里我们可以通过异步调用的方式,
防止脚本执行阻塞对主程序带来的负面影响。并且通过添加超时机制,
对脚本执行超时的线程进行强制关闭,避免有死循环嫌疑的恶意脚本对系统资源的恶意消耗。
程序示例
1.编写脚本执行线程
1 | /** |
说明:
- 线程中添加变量 done , 用来标志脚本执行正常结束的情况。
- run方法中调用execute()方法,execute执行完成将done标志位置为true。
- 通过isDOne()方法判断线程是否正常结束。
- 创建ScriptThread对象需要实现execute()方法,方法内部添加执行脚本的逻辑代码。
2.定义脚本执行超时异常类
1 | /** |
说明:
- 脚本执行超时后抛出ScriptTimeoutException对象,用来区分异常类型。
3.编写脚本执行阻塞方法
1 | /** |
说明:
调用该方法将阻塞等待,直到线程执行完毕或者线程超时,如果超时,则强制关闭线程。
(JDK Thread#stop()方法不推荐使用,在当前的特殊场景下,我们无法修改脚本逻辑,
无法在脚本内部控制线程的中断,因此需要使用stop方法对线程进行强制退出。)
4.编写脚本执行方法
1 | /** |
说明:
- 方法逻辑中首先新建脚本执行线程并提交线程的执行,接着调用等待方法阻塞等待脚本的执行,如果返回结果说明脚本超时,则抛出超时异常。
- 脚本执行线程execute方法体中定义执行脚本的逻辑,将执行脚本正常情况下的返回值、异常情况下的异常对象储存到map中。
- 如果脚本执行正常结束没有超时,则拿到map中的内容,若异常对象不为空则抛出异常对象;若异常对象为空则将脚本返回值返回。