我必须用 Java 编写一个“看门狗”,以确保线程不会执行太长时间。初始化对象没问题,我创建了一个类,它调用 WatchDog 和带有 run() 方法中的反射的构造函数。
线程很容易停止,但我如何保护对象的正常方法?例如我调用一个对象的方法,这个方法执行一个无限循环,你会怎么做?
谢谢
首先,我应该指出,停止线程并不容易。事实上,在一般情况下,线程是无法安全停止的:
您可以调用Thread.interrupt()
要停止的线程,但不能保证线程会注意到中断,更不用说实际停止了。
您可以调用已弃用的Thread.stop()
方法,但此方法不安全。如果你在一个不幸的时刻调用它,你可以让数据结构处于半更新状态,让其他线程(永远)等待不会到达的信号等等。
以下是我如何为方法执行实现看门狗。
首先,我将修改方法以向看门狗服务添加两个调用;例如
public void someMethod(...) {
Watchdog.startMethod(maxTime);
// do stuff
Watchdog.endMethod();
}
接下来,我将使用按到期时间排序的优先级队列来实现看门狗:
startMethod(maxTime)
将向队列中添加一个条目,其到期时间为now + maxTime
。该条目将包括对当前线程的引用(调用该方法时。endMethod()
将为当前线程寻找(该)队列条目,如果找到则将其删除。需要对数据结构和处理endMethod
跳过调用的情况进行一些思考。(事实上,由于一个方法调用可以因异常而终止,所以endMethod()
调用确实需要在一个finally
块中完成。)
请注意,startMethod
andendMethod
调用可以(并且可能应该)由注释处理器或类似的东西插入。
鉴于复杂性以及您不能保证(安全地)停止线程的事实,我会想到一些不涉及方法看门狗的解决方案。
对象的普通方法在某个线程上运行。它可能是 AWT 事件分派器或任何它被调用的东西。或者它可能是控制台应用程序的主线程。
它们与使用 new Thread() 调用的线程没有什么不同。
我猜你的看门狗需要查看 VM 中的所有线程并寻找利用率 >= 某个阈值的线程。
到目前为止你有什么代码?
富有的
尝试使用@Timeable
来自jcabi-aspects 的注释:
public class Resource {
@Timeable(limit = 5, unit = TimeUnit.SECONDS)
public String load(URL url) {
return url.openConnection().getContent();
}
}
您的方法将在超时时中断。