【问题标题】:How to secure methods in java (overflow and so on)如何保护java中的方法(溢出等)
【发布时间】:2011-08-09 11:52:20
【问题描述】:

我必须用 Java 编写一个“看门狗”,以确保线程不会执行太长时间。初始化对象没问题,我创建了一个类,它在 run() 方法中调用 WatchDog 和构造函数。

线程很容易停止,但我如何保护对象的正常方法? 比如我调用了一个Object的方法,这个方法执行了一个无限循环,你会怎么做呢?

谢谢

【问题讨论】:

  • “一个线程很容易停止”,不,不是。我不明白“我怎样才能保护对象的正常方法?”,也不是无限循环后面的例子。
  • download.oracle.com/javase/7/docs/technotes/guides/concurrency/… 阅读所有内容,然后检查您是否仍想调用 stop()。为了解决您的问题,或许有必要跳出常规思考。
  • 我不想做一个游戏,你可以在其中制定策略,如果他们做一段时间(1);我必须杀了他们,你现在明白我的意思了吗?

标签: java watchdog


【解决方案1】:

首先,我应该指出,停止线程不容易。事实上,一般情况下,线程是无法安全停止的:

  • 您可以在要停止的线程上调用Thread.interrupt(),但不能保证线程会注意到中断,更不用说实际停止了。

  • 您可以调用已弃用的Thread.stop() 方法,但此方法不安全。如果你在一个不幸的时刻调用它,你可以让数据结构处于半更新状态,让其他线程(永远)等待不会到达的信号等等。


以下是我如何为方法执行实现看门狗。

首先我将修改方法以添加两个对看门狗服务的调用;例如

public void someMethod(...) {
    Watchdog.startMethod(maxTime);
    // do stuff
    Watchdog.endMethod();
}

接下来,我将使用按到期时间排序的优先级队列来实现看门狗:

  1. startMethod(maxTime) 将向队列中添加一个条目,其到期时间为now + maxTime。该条目将包含对当前线程的引用(调用该方法时。
  2. endMethod() 将寻找当前线程的(该)队列条目,如果找到则将其删除。
  3. 看门狗线程会定期查看第一个队列条目。如果该条目的到期时间小于“现在”,则看门狗将删除该条目,停止其线程并检查下一个条目。重复直到下一个条目没有过期。

需要对数据结构和处理endMethod 调用被跳过的情况进行一些思考。 (确实,由于方法调用可能会因异常而终止,所以endMethod() 调用确实需要在finally 块中完成。)

请注意,startMethodendMethod 调用可以(并且可能应该)由注释处理器或类似的东西插入。


考虑到复杂性,以及您不能保证(安全地)停止线程的事实,我会想到一些不涉及方法看门狗的解决方案。

【讨论】:

  • 这是解决问题的正确方法。不知道为什么它没有被选为答案。如果有人想要开箱即用的解决方案,请尝试@ yegor256 提出的@ Timeable。但它并没有解决“中断后清理”的问题。就我个人而言,我仍然会写我自己的方面。
【解决方案2】:

对象的普通方法在一些线程上运行。它可能是 AWT 事件分派器或任何它被调用的东西。或者它可能是控制台应用程序的主线程。

它们与使用 new Thread() 调用的线程没有什么不同。

我猜你的看门狗需要查看 VM 中的所有线程并寻找利用率 >= 某个阈值的线程。

到目前为止你有什么代码?

丰富

【讨论】:

  • 好吧,也许我描述错了,我给了我的看门狗所有我想观察的线程。我只想初始化对象并运行线程中的每个方法,然后将该线程交给我的看门狗。
  • 嗨 Nicolas 你能详细说明一下吗?特别是“我只想初始化对象并运行线程中的每个方法,并将该线程交给我的看门狗。”部分。我可能会提供帮助,但我不明白你在做什么。
  • 这是我的安全实例代码和安全方法调用:pastebin.com/v8kdvdUW希望你能理解我想要做什么。
  • 嗨 Nicolas 刚刚看了看。有没有你没有粘贴过的类看门狗?此外,您在几个地方都可以有效地忽略 InterruptedException。您绝对不能忽略该异常。以我的经验,所有线程操作都可以并且确实会被中断;调度程序唤醒他们,因为上帝知道是什么原因,然后他们抛出那个异常。您必须围绕这些 try-catch 块进行一个小循环,以寻找退出条件。
【解决方案3】:

尝试使用jcabi-aspects中的@Timeable注解:

public class Resource {
  @Timeable(limit = 5, unit = TimeUnit.SECONDS)
  public String load(URL url) {
    return url.openConnection().getContent();
  }
}

您的方法将在超时时中断。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-18
    • 2011-08-04
    • 2013-04-07
    • 2016-10-11
    • 2013-01-02
    • 2015-12-25
    相关资源
    最近更新 更多