Atanan görevlerinden biri herhangi bir nedenle başarısız olduğunda Java stop yürütücü hizmeti


12

Birkaç görevi aynı anda ve 1 dakika arayla 1 dakika boyunca çalıştıracak bir tür hizmete ihtiyacım var.

Görevlerden biri başarısız olursa, hizmeti ve bir şeylerin yanlış gittiğini gösteren bir tür gösterge ile koşan her görevi durdurmak istiyorum, aksi takdirde bir dakika sonra her şey iyi gittiğinde servis her şeyin iyi gittiğini gösteren bir gösterge ile duracaktır.

Örneğin, 2 fonksiyonum var:

Runnable task1 = ()->{
      int num = Math.rand(1,100);
      if (num < 5){
          throw new Exception("something went wrong with this task,terminate");
      }
}

Runnable task2 = ()->{
      int num = Math.rand(1,100)
      return num < 50;
}



ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(2);
task1schedule = scheduledExecutorService.scheduleAtFixedRate(task1, 1, 60, TimeUnit.SECONDS);
task2schedule = scheduledExecutorService.scheduleAtFixedRate(task2, 1, 60, TimeUnit.SECONDS);

if (!task1schedule || !task2schedule) scheduledExecutorService.shutdown();

Bununla nasıl başa çıkabileceğim ve işleri olabildiğince genel hale getireceğim hakkında herhangi bir fikrim var mı?


1
Asıl soru dışında birkaç şey Math.randyerleşik bir API değildir. Uygulamasının Runnablebir void runtanımı olmalıdır . Tipi task1/2scheduleolacağını ScheduledFuture<?>sağlanan bağlamda. Asıl soruya geçersek, nasıl faydalanılır awaitTermination? Bunu şu şekilde yapabilirsiniz scheduledExecutorService.awaitTermination(1,TimeUnit.MINUTES);. Alternatif olarak, görevlerden herhangi birinin normal tamamlanmadan önce iptal edilip edilmediğini kontrol etmeye ne dersiniz if (task1schedule.isCancelled() || task2schedule.isCancelled()) scheduledExecutorService.shutdown();?
Naman

2
Görevlerin her dakika tekrarlanmasının bir anlamı yoktur , ancak daha sonra “bir dakika sonra her şey yolunda giderse” görevleri durdurmak istediğinizi söyleyin. Her iki durumda da yürütücüyü durdurduğunuz için, yürütücüyü bir dakika sonra kapatan bir görev zamanlamak önemsizdir. Ve vadeli işlemler zaten bir şeyin yanlış olup olmadığını gösteriyor. Başka ne tür bir gösterge istediğinizi söylemediniz.
Holger

Yanıtlar:


8

Fikir, görevlerin ortak bir nesneye TaskCompleteEvent itmesidir. Eğer bir hata yaparlarsa, zamanlayıcı durdurulur ve tüm görevler durur.

"Hata" ve "başarı" haritalarındaki her görev yinelemesinin sonuçlarını kontrol edebilirsiniz.

public class SchedulerTest {

    @Test
    public void scheduler() throws InterruptedException {
        ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(2);
        TaskCompleteEvent taskCompleteEvent = new TaskCompleteEvent(scheduledExecutorService);
        Runnable task1 = () -> {
            int num = new Random().nextInt(100);
            if (num < 5) {
                taskCompleteEvent.message("task1-"+UUID.randomUUID().toString(), "Num "+num+" was obatined. Breaking all the executions.", true);
            }
        };
        Runnable task2 = () -> {
            int num = new Random().nextInt(100);
            taskCompleteEvent.message("task2-"+UUID.randomUUID().toString(), num < 50, false);
        };
        scheduledExecutorService.scheduleAtFixedRate(task1, 0, 1, TimeUnit.SECONDS);
        scheduledExecutorService.scheduleAtFixedRate(task2, 0, 1, TimeUnit.SECONDS);
        scheduledExecutorService.awaitTermination(60, TimeUnit.SECONDS);
        System.out.println("Success: "+taskCompleteEvent.getSuccess());
        System.out.println("Errors: "+taskCompleteEvent.getErrors());
        System.out.println("Went well?: "+taskCompleteEvent.getErrors().isEmpty());
    }

    public static class TaskCompleteEvent {

        private final ScheduledExecutorService scheduledExecutorService;
        private final Map<String, Object> errors = new LinkedHashMap<>();
        private final Map<String, Object> success = new LinkedHashMap<>();

        public TaskCompleteEvent(ScheduledExecutorService scheduledExecutorService) {
            this.scheduledExecutorService = scheduledExecutorService;
        }

        public synchronized void message(String id, Object response, boolean error) {
            if (error) {
                errors.put(id, response);
                scheduledExecutorService.shutdown();
            } else {
                success.put(id, response);
            }
        }

        public synchronized Map<String, Object> getErrors() {
            return errors;
        }

        public synchronized Map<String, Object> getSuccess() {
            return success;
        }

    }

}

2

Sadece işi diğer tüm çalışan görevleri izlemek olan ek bir görev eklemeniz gerekir - ve izlenen görevlerden herhangi biri başarısız olduğunda, suikastçının inceleyebileceği bir semafor (bayrak) ayarlamaları gerekir.

    ScheduledExecutorService executor = (ScheduledExecutorService) Executors.newScheduledThreadPool(2);

    // INSTANTIATE THE REMOTE-FILE-MONITOR:
    RemoteFileMonitor monitor = new RemoteFileMonitor(remotesource, localtarget);

    // THIS TimerTask PERIODICALLY TRIGGERS THE RemoteFileMonitor: 
    TimerTask remote = new TimerTask() {

        // RUN FORREST... RUN !
        public void run() {

            try { 

                kae.trace("TimerTask::run() --> Calling RemoteFileMonitor.check()");
                monitor.check();

            } catch (Exception ex) {

                // NULL TRAP: ALLOWS US TO CONTINUE AND RETRY:

            }

        }

    };

    // THIS TimerTask PERIODICALLY TRIES TO KILL THE REMOTE-FILE-MONITOR:
    TimerTask assassin = new TimerTask() {

        // WHERE DO BAD FOLKS GO WHEN THEY DIE ? 
        private final LocalDateTime death = LocalDateTime.now().plus(ConfigurationOptions.getPollingCycleTime(), ChronoUnit.MINUTES);

        // RUN FORREST... RUN !
        public void run() {

            // IS THERE LIFE AFTER DEATH ???
            if (LocalDateTime.now().isAfter(death)) {

                // THEY GO TO A LAKE OF FIRE AND FRY:
                kae.error(ReturnCode.MONITOR_POLLING_CYCLE_EXCEEDED);                   

            }

        }

    };

    // SCHEDULE THE PERIODIC EXECUTION OF THE RemoteFileMonitor: (remote --> run() monitor --> check())
    executor.scheduleAtFixedRate(remote, delay, interval, TimeUnit.MINUTES);

    // SCHEDULE PERIODIC ASSASSINATION ATTEMPTS AGAINST THE RemoteFileMonitor: (assassin --> run() --> after death --> die())
    executor.scheduleAtFixedRate(assassin, delay, 60L, TimeUnit.SECONDS);

    // LOOP UNTIL THE MONITOR COMPLETES:
    do {

        try {

            // I THINK I NEED A NAP:
            Thread.sleep(interval * 10);                

        } catch (InterruptedException e) {

            // FAIL && THEN cleanexit();
            kae.error(ReturnCode.MONITORING_ERROR, "Monitoring of the XXXXXX-Ingestion site was interrupted");

        }

        // NOTE: THE MONITOR IS SET TO 'FINISHED' WHEN THE DONE-File IS DELIVERED AND RETRIEVED:
    } while (monitor.isNotFinished());

    // SHUTDOWN THE MONITOR TASK:
    executor.shutdown();

2
Sınıf TimerTasktamamen ilgisizdir ScheduledExecutorService; sadece uygulamak için olur Runnable. Ayrıca, belirli bir zamana ( ConfigurationOptions.getPollingCycleTime()) ulaşılıp ulaşılmadığını kontrol etmek için periyodik bir görev zamanlamak mantıklı değildir . Bir a'nız var ScheduledExecutorService, böylece görevi istediğiniz zaman için doğru şekilde zamanlamasını söyleyebilirsiniz.
Holger

Kullandığım örnekteki uygulama, görev tamamlanmadıysa, belirli bir süre sonra bir yürütme görevini öldürmekti. Kullanım senaryosu şuydu: Uzak sunucu 2 saat içinde bir dosyayı düşürmediyse - görevi öldürün. OP bunu istedi.
Greg Patnude

Yorumumu okudun ve anladın mı? Sadece yerine, bu sebepsiz bir cesareti sınıfını kullanır, kod ne önemi yoktur TimerTaskile Runnableve kod ne yaptığını değiştirmeden, sorunu düzelttik. Ayrıca, sadece kullanın executor.schedule(assassin, ConfigurationOptions.getPollingCycleTime(), ChronoUnit.MINUTES);ve istenen zamanda bir kez çalışacaktır, bu nedenle if(LocalDateTime.now().isAfter(death))kontrol eski. Yine, kodun yaptığı şeyi değiştirmez, bunun yanı sıra bunu oldukça basit ve daha verimli hale getirir.
Holger
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.