Как перенести задачу с помощью ScheduledExecutorService? - PullRequest
11 голосов
/ 12 марта 2009

Я видел это в документации по Java: ScheduledAtFixedRate , там написано

При любом выполнении задания встречает исключение, последующее казни подавлены

Я не хочу, чтобы это происходило в моем приложении. Даже если я увижу исключение, я всегда хочу, чтобы последующие исполнения происходили и продолжались. Как я могу получить это поведение от ScheduledExecutorService.

Ответы [ 4 ]

7 голосов
/ 12 марта 2009

Окружите метод Callable.call или метод Runnable.run с помощью try / catch ...

Например:

public void run()
{
    try
    {
        // ... code
    }
    catch(final IOException ex)
    {
        // handle it
    }
    catch(final RuntimeException ex)
    {
        // handle it
    }
    catch(final Exception ex)
    {
        // handle it
    }
    catch(final Error ex)
    {
        // handle it
    }
    catch(final Throwable ex)
    {
        // handle it
    }
}

Обратите внимание, что перехватывать что-либо кроме того, что вам говорит компилятор (исключение IOException в моем примере), не очень хорошая идея, но бывают случаи, и это звучит как один из них, что это может сработать, если вы обращайтесь с ним правильно.

Помните, что такие вещи, как ошибка, очень плохи - у виртуальной машины не хватает памяти и т. Д., Поэтому будьте осторожны с их обработкой (именно поэтому я разделил их на их собственные обработчики, а не просто выполнял catch (final Throwable ex ) и больше ничего).

2 голосов
/ 10 мая 2012

Попробуйте VerboseRunnable класс из jcabi-log , который выполняет упаковку, предложенную TofuBeer:

import com.jcabi.log.VerboseRunnable;
Runnable runnable = new VerboseRunnable(
  Runnable() {
    public void run() { 
      // do business logic, may Exception occurs
    }
  },
  true // it means that all exceptions will be swallowed and logged
);

Теперь, когда кто-то звонит runnable.run(), исключений не выдается. Вместо этого они проглатываются и регистрируются (в SLF4J).

1 голос
/ 05 октября 2012

Если все, что вам нужно, это последующие выполнения и продолжение даже после исключений, этот код должен работать.

 ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();    

 Runnable task = new Runnable() {      
  @Override
  public void run() {
   try{
      System.out.println(new Date() + " printing");
      if(true)
        throw new RuntimeException();

   } catch (Exception exc) {
      System.out.println(" WARN...task will continiue"+ 
            "running even after an Exception has araised");
    }
  }      
};

executor.scheduleAtFixedRate(task, 0, 3, TimeUnit.SECONDS);

Если произошло Throwable, отличное от Exception, возможно, вы не захотите, чтобы выполнялись последующие исполнения.

Вот вывод

Пт, 23 ноября 12:09:38 Печать JST 2012
_WARN ... задача будет Continiuerunning даже после повышения исключения
пт 23 ноября 12:09:41 JST 2012 печать
_WARN ... задача будет продолжаться даже после повышения исключения
пт 23 ноября 12:09:44 JST 2012 печать
_WARN ... задание будет продолжать работать даже после Возникло исключение
пт 23 ноября 12:09:47 JST 2012 типография
_WARN ... задание будет продолжать выполняться даже после того, как исключение поднялось

1 голос
/ 06 октября 2010

У меня была такая же проблема. Я также пробовал этот блок try внутри метода run (), но он не работает.

Итак, я сделал что-то работает, пока:

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;

public class Test2 {

    static final ExecutorService pool = Executors.newFixedThreadPool(3);

    static final R1 r1 = new R1();
    static final R2 r2 = new R2();

    static final BlockingQueue deadRunnablesQueue = new LinkedBlockingQueue<IdentifiableRunnable>();

    static final Runnable supervisor = new Supervisor(pool, deadRunnablesQueue);

    public static void main(String[] args) {
        pool.submit(r1);
        pool.submit(r2);
        new Thread(supervisor).start();
    }

    static void reSubmit(IdentifiableRunnable r) {
        System.out.println("given to an error, runnable [" + r.getId()
                + "] will be resubmited");
        deadRunnablesQueue.add(r);
    }

    static interface IdentifiableRunnable extends Runnable {
        String getId();
    }

    static class Supervisor implements Runnable {
        private final ExecutorService pool;
        private final BlockingQueue<IdentifiableRunnable> deadRunnablesQueue;

        Supervisor(final ExecutorService pool,
                final BlockingQueue<IdentifiableRunnable> deadRunnablesQueue) {
            this.pool = pool;
            this.deadRunnablesQueue = deadRunnablesQueue;
        }

        @Override
        public void run() {
            while (true) {
                IdentifiableRunnable r = null;
                System.out.println("");
                System.out
                        .println("Supervisor will wait for a new runnable in order to resubmit it...");
                try {
                    System.out.println();
                    r = deadRunnablesQueue.take();
                } catch (InterruptedException e) {
                }
                if (r != null) {
                    System.out.println("Supervisor got runnable [" + r.getId()
                            + "] to resubmit ");
                    pool.submit(r);
                }
            }
        }
    }

    static class R1 implements IdentifiableRunnable {
        private final String id = "R1";
        private long l;

        @Override
        public void run() {
            while (true) {
                System.out.println("R1 " + (l++));
                try {
                    Thread.currentThread().sleep(5000);
                } catch (InterruptedException e) {
                    System.err.println("R1 InterruptedException:");
                }
            }
        }

        public String getId() {
            return id;
        }
    }

    static class R2 implements IdentifiableRunnable {
        private final String id = "R2";
        private long l;

        @Override
        public void run() {
            try {
                while (true) {
                    System.out.println("R2 " + (l++));
                    try {
                        Thread.currentThread().sleep(5000);
                    } catch (InterruptedException e) {
                        System.err.println("R2 InterruptedException:");
                    }
                    if (l == 3) {
                        throw new RuntimeException(
                                "R2 error.. Should I continue to process ? ");
                    }
                }
            } catch (final Throwable t) {
                t.printStackTrace();
                Test2.reSubmit(this);
            }
        }

        public String getId() {
            return id;
        }
    }

}

Вы можете попробовать закомментировать Test2.reSubmit (this), чтобы увидеть, что без него R2 перестанет работать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...