【问题标题】:OSGi background thread failureOSGi 后台线程失败
【发布时间】:2013-01-09 21:48:04
【问题描述】:

BundleActivator 运行后台线程,而该后台线程出现不可恢复的错误怎么办?

public class Activator implements BundleActivator
{
   private Thread t;
   @Override
   public void start(BundleContext context) throws Exception
   {
      t = new Thread(new Runnable(){
            @Override
             public void run(){
                while (!Thread.interrupted()){
                  // do something which may throw a runtime exception
               }
            }
         });
      t.start();
   }
   @Override void stop(BundleContext context) throws Exception
   {
      t.interrupt();
      t.join();
   }
}

通过这个示例,我如何通知 OSGi 框架线程已死并且捆绑包已有效停止且未运行?

【问题讨论】:

    标签: java multithreading osgi


    【解决方案1】:

    看看 Peter Kriens 在this article 中是如何执行类似操作的。对于他的示例,您需要做的就是在他的 catch 块中调用激活器上的停止,而不是执行 printStackTrace。

    【讨论】:

    • 此页面上的 cmets 是 2007 年制作的,建议进一步讨论。没有更新的信息吗?
    • 似乎链接已失效。我找到了这个one,它似乎与原来的很接近。
    【解决方案2】:

    也许最好的办法就是记录错误,最好是记录到 OSGi 日志服务。然后管理员可以检测捆绑包的问题并决定要做什么。您应该将其实现为声明式服务组件而不是 BundleActivator,因为这将使您更容易访问日志服务,并且您还可以在捆绑包中拥有多个这些东西。

    我不认为捆绑包应该尝试自行停止。这使捆绑包处于一种奇怪的状态......它已停止但仍有代码运行......即调用stop()的代码。这可能只是短暂的,但感觉不对。

    处于 ACTIVE 状态的捆绑软件不一定必须一直“做某事”,它只是具有“做某事”的潜力。失败的事实不应该真正影响包的外部状态。

    【讨论】:

    • 难道不是一个捆绑包,列为“活动”,但处于失败状态也是一种奇怪的状态?该示例实际上是生产中的监视线程,它从串行端口读取并中继消息。据我所知,这不是可以作为声明式服务完成的。
    • 不,我不这么认为。这是对包的 ACTIVE 状态所暗示的含义的误解。是的,您可以将其作为 DS 组件执行.... DS 组件可以做BundleActivator 可以做的任何事情(以及更多)。
    • 我找不到任何关于 DS 及其在线工作方式的明确文档。你有什么指示吗?我的理解是 DS 仅用于提供和消费服务。此外,ACTIVE 和 RESOLVED 之间的区别是什么?我的假设是 ACTIVE 旨在表示无论提供或执行的捆绑包实际上正在提供或完成。
    • DS 规范相当清楚,否则请尝试“OSGi in Action”一书。 DS 确实允许您提供和使用服务,但 DS 组件也可以具有激活/停用方法,就像 BundleActivator。这就是为什么我说 DS 组件可以做任何 BundleActivator 可以做的事情,甚至更多。
    • 关于你问题的第二部分......正如我所说,ACTIVE 状态表示捆绑包正在做某事的潜在,而不是保证 就是这样。
    【解决方案3】:

    据我所知,OSGi 在这种特殊情况下无法直接帮助您。我通常依靠uncaught exception handlers 来获得线程崩溃的通知,或者我实现了某种形式的软件看门狗。

    关键是,即使其中一个线程在一段时间后崩溃,生成多个线程并成功完成其启动方法的包仍保持活动状态。

    【讨论】:

      【解决方案4】:

      尼尔(和往常一样)非常正确。捆绑包永远不应停止自身,因为这会干扰管理代理。启动/停止是从该管理代理到捆绑包的消息,表明它应该处于活动状态。如果捆绑包无法履行其职责,您应该记录该消息,稍等片刻(越来越长)并重试。

      日志是通知的地方,停止捆绑会严重混合级别。

      【讨论】:

      • 我正在尝试的不是通知,而是自动恢复。由于这不是一个已发布的服务,而是一个守护线程,我不确定“重试”将如何工作。这是否也意味着你的文章@aqute.biz/Snippets/Stop不再有效,或者在其他情况下有效。
      • sn-p 只是为了表明您可以做到,但绝不是建议您这样做。守护程序通常会失败,因为存在暂时性问题。例如。互联网已关闭。继续记录,稍等,然后重试。无论如何,计算机不能做很多其他事情。
      • 如果错误状态是可恢复或可重试的,那么线程本身应该尝试恢复或重试。如果不是(或者如果重试也反复失败),那么最终人工操作员必须进行干预。日志服务是bundle向操作员发送通知的标准方式。
      • 感谢您的宝贵时间。我正在努力使我的服务尽可能地防弹。我的期望是捆绑状态可以以某种方式用于指示捆绑的健康状况。我的理由是,当捆绑包的健康受到威胁时,我可以提醒运行时或卸载捆绑包以反映健康问题。从这次对话看来,我希望它能够让后台线程在可预测的状态下保持活动状态,以及在意外线程死亡时可能的 System.exit(1) 吗?
      • 从不,从不,从不 System.exit ... OSGi 规范清楚地将系统管理的责任与(希望的)可重用部分的责任分开。如果你执行 System.exit 或停止你的包,你会得到一个不可重用的组件,因为它不能再被 mamaged。凝聚力……只做你负责的事情。高度内聚的系统允许多种组合,组合使您必须在许多变体中编写相同的功能。
      猜你喜欢
      • 2015-10-04
      • 1970-01-01
      • 1970-01-01
      • 2019-10-17
      • 1970-01-01
      • 2019-09-09
      • 2016-03-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多