Porting code from using timers to scheduledexecutorservice

前端 未结 3 1331
终归单人心
终归单人心 2021-01-15 16:31

I am trying to port code from using java timers to using scheduledexecutorservice

I have the following use case

class A {

    public boolean execut         


        
相关标签:
3条回答
  • 2021-01-15 17:15

    NOTE: The way you did this will leak threads!

    If your class B will be kept around and each instance will eventually be closed or shut down or released, I would do it like this:

    class B {
      final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
    
      public boolean execute() {
        try {
          scheduler.scheduleWithFixedDelay(new BRunnnableTask(), period, delay);
          return true;
        } catch (Exception e) {
          return false;
        }
      }
    
      public void close() {
        scheduler.shutdownNow();
      }
    }
    

    If you will not do this kind of cleanup on each instance, then I would instead do this:

    class B {
      static final ScheduledExecutorService SCHEDULER = Executors.newCachedThreadPool();
    
      public boolean execute() {
        try {
          SCHEDULER.scheduleWithFixedDelay(new BRunnnableTask(), period, delay);
          return true;
        } catch (Exception e) {
          return false;
        }
      }
    }
    

    Each ExecutorService you allocate in your code allocates a single Thread. If you make many instances of your class B then each instance will be allocated a Thread. If these don't get garbage collected quickly, then you can end up with many thousands of threads allocated (but not used, just allocated) and you can crash your whole server, starving every process on the machine, not just your own JVM. I've seen it happen on Windows and I expect it can happen on other OS's as well.

    A static Cached thread pool is very often a safe solution when you don't intend to use lifecycle methods on the individual object instances, as you'll only keep as many threads as are actually running and not one for each instance you create that is not yet garbage collected.

    0 讨论(0)
  • 2021-01-15 17:20

    It looks ok. Depending on what you're doing, you may want to keep executor service around as a member so you can use it again. Also, you can get a ScheduledFuture back from the scheduleXX() methods. This is useful because you can call get() on it to pull any exceptions that occur in the timed thread back to your control thread for handling.

    0 讨论(0)
  • 2021-01-15 17:23

    There is currently no good way to handle repeating tasks in the Executors framework.

    It really wasn't designed with this use case in mind, and there is no realistic way to avoid swallowing exceptions.

    If you really must use it for repeating tasks, each scheduling should look something like this:

    scheduler.scheduleWithFixedDelay(new Runnable() {
      public void run() {
         try {
           .. your normal code here...
         } catch (Throwable t) {
           // handle exceptions there
         }
      }
    }, period, delay);
    
    0 讨论(0)
提交回复
热议问题