Java Executor Best Practices for Tasks that Should Run Forever

后端 未结 4 1201
不知归路
不知归路 2020-12-22 19:20

I\'m working on a Java project where I need to have multiple tasks running asynchronously. I\'m led to believe Executor is the best way for me to do this, so I\'m familiari

相关标签:
4条回答
  • 2020-12-22 19:25

    Aside to eyeballing it, I generally run Java code against static analysis tools like PMD and FindBugs to look for deeper issues.

    Specifically for this code FindBugs didn't like that results1 and results2 are not volatile in the lazy init, and that the run() methods might ignore the Exception because they aren't explicitly being handled.

    In general I am a bit leery of the use of Thread.sleep for concurrency testing, preferring timers or terminating states/conditions. Callable might be useful in returning something in the event of a disruption that throws an exception if unable to compute a result.

    For some best practices and more food for thought, check out Concurrency in Practice.

    0 讨论(0)
  • 2020-12-22 19:33

    I faced a similar situation in my previous project, and after my code blew in the face of an angry customer, my buddies and I added two big safe-guards:

    1. In the infinite loop, catch Errors too, not just exceptions. Sometimes unexcepted things happen and Java throws an Error at you, not an Exception.
    2. Use a back-off switch, so if something goes wrong and is non-recoverable, you don't escalate the situation by eagerly starting another loop. Instead, you need to wait until the situation goes back to normal and then start again.

    For example, we had a situation where the database went down and during the loop an SQLException was thrown. The unfortunate result was that the code went through the loop again, only to hit the same exception again, and so forth. The logs showed that we hit the same SQLException about 300 times in a second!! ... this happened intermittently several times with occassional JVM pauses of 5 seconds or so, during which the application was not responsive, until eventually an Error was thrown and the thread died!

    So we implemented a back-off strategy, approximately shown in the code below, that if the exception is not recoverable (or is excepted to recover within a matter of minutes), then we wait for a longer time before resuming operations.

    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) {
          }
        }
      }
    }
    

    If you implement your tasks this way then I don't see a point in having a third "watch-dog" thread with the checkTasks() method. Furthermore, for the same reasons I outlined above, I'd be cautious to just start the task again with the executor. First you need to understand why the task failed and whether the environment is in a stable condition that running the task again would be useful.

    0 讨论(0)
  • 2020-12-22 19:42

    have you tried Quartz framework ?

    0 讨论(0)
  • 2020-12-22 19:43

    how about this

    Runnable task = () -> {
      try{
        // do the task steps here
      } catch (Exception e){
        Thread.sleep (TIME_FOR_LONGER_BREAK);
      }    
    };
    ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
    executor.scheduleAtFixedRate(task,0, 0,TimeUnit.SECONDS);
    
    0 讨论(0)
提交回复
热议问题