当前位置: 首页 > 面试题库 >

适用于应永久运行的任务的Java Executor最佳实践

甘永春
2023-03-14
问题内容

我正在一个Java项目中,我需要让多个任务异步运行。我被认为是执行器是执行此操作的最佳方法,因此我已经熟悉了它。(是的,要获得报酬来学习!)但是,我尚不清楚最好的方法是完成我想做的事情。

为了争辩,假设我有两个任务正在运行。两者都不会终止,并且都应该在应用程序的生存期内运行。我正在尝试编写一个主包装器类,例如:

  • 如果任一任务引发异常,则包装器将捕获该异常并重新启动任务。
  • 如果任一个任务运行完毕,包装器将注意到并重新启动任务。

现在,应该注意的是,这两个任务的实现都将代码包裹run()在一个永远不会运行完成的无限循环中,并带有一个try /
catch块,该块应处理所有运行时异常而不会破坏该循环。我正在尝试增加另一层确定性。如果我或跟随我的某人做一些愚蠢的事情破坏了这些安全措施并中止了任务,则应用程序需要做出适当的反应。

有没有比我建议的经验更多的人来解决这个问题的最佳实践?

FWIW,我准备了这个html" target="_blank">html" target="_blank">测试课程:

public class ExecTest {

   private static ExecutorService executor = null;
   private static Future results1 = null;
   private static Future results2 = null;

   public static void main(String[] args) {
      executor = Executors.newFixedThreadPool(2);
      while(true) {
         try {
            checkTasks();
            Thread.sleep(1000);
         }
         catch (Exception e) {
            System.err.println("Caught exception: " + e.getMessage());
         }
      }
   }

   private static void checkTasks() throws Exception{
      if (results1 == null || results1.isDone() || results1.isCancelled()) {
         results1 = executor.submit(new Test1());
      }

      if (results2 == null || results2.isDone() || results2.isCancelled()) {
         results2 = executor.submit(new Test2());
      }
   }
}

class Test1 implements Runnable {
   public void run() {
      while(true) {
         System.out.println("I'm test class 1");
         try {Thread.sleep(1000);} catch (Exception e) {}
      }

   }
}

class Test2 implements Runnable {
   public void run() {
      while(true) {
         System.out.println("I'm test class 2");
         try {Thread.sleep(1000);} catch (Exception e) {}
      }
   }
}

它的行为方式是我想要的,但我不知道是否有任何陷阱,效率低下或彻头彻尾的错误观念等着让我感到惊讶。(实际上,考虑到我是新手,如果 没有
什么不对劲/不可思议之处,我会感到震惊。)

欢迎任何见识。


问题答案:

在上一个项目中,我遇到了类似的情况,面对愤怒的客户,我的代码崩溃后,我的好友和我添加了两个重要的安全措施:

  1. 在无限循环中,也要捕获错误,而不仅仅是异常。有时会发生异常情况,并且Java向您抛出错误,而不是Exception。
  2. 使用退避开关,因此,如果出现问题并且无法恢复,则不会急于启动另一个循环来升级情况。相反,您需要等到情况恢复正常后再重新开始。

例如,我们遇到一种情况,即数据库崩溃了,并且在循环期间抛出了SQLException。不幸的结果是代码再次经历了循环,仅再次遇到了相同的异常,依此类推。日志显示,我们在一秒钟内命中了相同的SQLException大约300次!!…这间歇性地发生了几次,偶尔的JVM暂停大约5秒钟,在此期间应用程序没有响应,直到最终抛出错误并且线程死亡!

因此,我们实施了一个退避策略,大致在下面的代码中显示,如果异常不可恢复(或被排除在几分钟之内恢复),那么我们将等待更长的时间才能恢复操作。

class Test1 implements Runnable {
  public void run() {
    boolean backoff = false;
    while(true) {
      if (backoff) {
        Thread.sleep (TIME_FOR_LONGER_BREAK);
        backoff = false;
      }
      System.out.println("I'm test class 1");
      try {
        // do important stuff here, use database and other critical resources
      }
      catch (SqlException se) {
       // code to delay the next loop
       backoff = true;
      }
      catch (Exception e) {
      }
      catch (Throwable t) {
      }
    }
  }
}

如果您以这种方式执行任务,那么使用checkTasks()方法创建第三个“看门狗”线程将毫无意义。此外,出于与我上面概述的相同原因,我会谨慎地再次与执行程序一起开始执行任务。首先,您需要了解任务失败的原因以及环境是否处于稳定状态,再次运行任务会很有用。



 类似资料:
  • 我有一个小型Android应用程序,我需要每隔几秒钟在其中执行一些FTP操作。在学习了在UI线程上运行网络内容是Android不喜欢的艰难方式后,我想到了这个解决方案: 这是执行不能直接在UI线程上运行的重复任务的好做法吗?此外,而不是通过调用始终创建一个新的Asyncask对象 创建< code>CheckFtpTask对象一次,然后重用它,这是一种选择吗?还是会给我带来副作用? 先谢谢你Jen

  • 问题内容: 在Debian服务器上,我安装了Node.js。我了解如何使用以下命令行从腻子启动应用程序: 并通过地址(IP和端口)访问它。 但是,一旦我关闭腻子,那我就无法到达地址了。 如何使Node.js应用程序永久运行? 如您所料,我是Linux和Node.js的初学者。 问题答案: 尽管其他答案解决了OP的问题,但它们都是过大的,不能解释为什么他或她遇到此问题。 关键是这一行,“我关闭油灰,

  • 问题内容: 哪种Java的CLI解析器比其他CLI解析器更易于使用和扩展? 问题答案: 这里是一些最受欢迎的。它们都是非常漂亮的功能,并且使用了前两个,我可以推荐它们。 Commons CLI http://commons.apache.org/cli/ Java宝石 http://code.google.com/p/javagems/ picocli (具有彩色使用帮助和自动完成功能) http

  • 问题内容: 什么是HSQLDB数据库的最佳浏览器工具? 问题答案: HSQL具有称为数据库管理器的内置GUI查询工具。在数据库文件的目录中运行: 然后将配置设置为: 允许我以非常方便的方式编辑所需内容。

  • 问题内容: 我需要阅读较小的XML文件(最多只有几MB,UTF-8编码),四处寻找各种元素和属性,也许要修改一些并将XML重新写回磁盘(最好采用缩进格式) 。 什么是满足我需求的最佳XML解析器?有很多可供选择。我知道的一些是: JDOM Woodstox XOM dom4j VTD-XML Xerces-J Crimson 当然是JDK中的那个(我正在使用Java 6)。我对Xerces很熟悉,

  • 问题内容: 我以前使用过XML Parser,尽管它工作正常,但总体上我并不满意,感觉好像我在使用变通办法来处理应该是基本功能的事情。 我最近看到了SimpleXML,但还没有尝试过。有没有更简单的方法?两者都有哪些优点和缺点?您使用过其他解析器吗? 问题答案: 我不得不说,SimpleXML是蛋糕,因为它首先是用C编写的扩展,并且非常快。但第二,解析后的文档采用PHP对象的形式。这样您就可以像“