2010-10-06 48 views
38

İstisnalar yemek gibi görünen bir ScheduledThreadPoolExecutor var. Gönderilen bir Runnable bir istisna atarsa, icracı servisimin beni bilgilendirmesini istiyorum.ThreadPools'ta özel durum yönetimi

Örneğin, ben bir yan soru olarak IndexArrayOutOfBoundsException en StackTrace

threadPool.scheduleAtFixedRate(
    new Runnable() { 
    public void run() { 
     int[] array = new array[0]; 
     array[42] = 5; 
    } 
    }, 
    1000, 
    1500L, 
    TimeUnit.MILLISECONDS); 

yazdırmak en azından aşağıdaki kodu istiyorum. ScheduledThreadPoolExecutor için genel bir try catch bloğu yazmanın bir yolu var mı? ORİJİNAL SORU

////////// SON //////////////

olarak aşağıdaki Dekoratör iyi çalışıyor önerdi.

public class CatcherTask implements Runnable{ 

    Runnable runMe; 

    public CatcherTask(Runnable runMe) { 
     this.runMe = runMe; 
    } 

    public void run() { 
     try { 
      runMe.run(); 
     } catch (Exception ex){ 
      ex.printStackTrace(); 
     } 
    } 
} 
+3

Mükemmel bir soru. Acaba neden sadece birkaç insan bu işe karışıyor? – whiskeysierra

+0

Ayrıca bkz. Http://stackoverflow.com/questions/1687977/how-to-properly-catch-runtimeexceptions-from-executors – Raedwald

cevap

22

Bu sorun hakkında bir süre önce küçük bir post yazdım.

  • ancak bunun yerine bir UncaughtExceptionHandler atama Mark Peters solution değiştirilmiş bir sürümünü kullanın (her yürütür hangi kendinize ait bir çalıştırılabilir içine çalıştırılabilir ibraz sarmak

    1. Colin Herbert tarafından sağlanan solution veya
    2. kullanın: İki seçeneğiniz vardır Bir try-catch-blok içinde gerçek runnable run çağırır.

    DÜZENLEME
    olarak, Runnable yerine ThreadFactory geçirilen birinin ScheduledExecutorService geçirilen sarmak için önemli, Mark dikkat çekti.

  • +0

    Tamam, bunu doğruladım ve cevabımı sildim. Teşekkürler! Ayrıntılara gitmek için adım 2'nizi değiştirmekten çekinmeyin. –

    +2

    Aslında # 2 denedim ve işe yaramaya gelemedim. İstisna, RunNable delegating içinde benim try/catch bloğumun üstünde iyi yakalandı, bu yüzden UncaughtExceptionHandler ile aynı soruna yenik görünmektedir. –

    +0

    Bunu kabul ettim - Ama Mark diyor ki, verilen görevleri bir try/catch ile dekore etmiyor ... Bunu deneyeceğim. – Ivan

    12

    Uyarı: Bu yöntem planlanan parçacığı havuzu emirleri yerine getirenlerin uygulanamaz. Bu yanıt, diğer iş parçacığı havuzu yürütücülerle olan ilişkisi nedeniyle geri alındı. Bakınız Willi's answer. ThreadFactory Parçacıkları bir UncaughtExceptionHandler vermek

    geçersiz kılma:

    ThreadPoolExecutor exec = new ThreadPoolExecutor...; 
    
    exec.setThreadFactory(new ExceptionCatchingThreadFactory(exec.getThreadFactory())); 
    //go on to submit tasks... 
    
    
    private static class ExceptionCatchingThreadFactory implements ThreadFactory { 
        private final ThreadFactory delegate; 
    
        private ExceptionCatchingThreadFactory(ThreadFactory delegate) { 
         this.delegate = delegate; 
        } 
    
        public Thread newThread(final Runnable r) { 
         Thread t = delegate.newThread(r); 
         t.setUncaughtExceptionHandler(new UncaughtExceptionHandler() { 
          @Override 
          public void uncaughtException(Thread t, Throwable e) { 
           e.printStackTrace(); //replace with your handling logic. 
          } 
         }); 
         return t; 
        } 
    } 
    
    +4

    'UncaughExceptionHandler' planlanan runable'larla çalışmaz. – whiskeysierra

    +0

    @Willi: Doğrulamama izin ver ve onaylarsam sileceğim. –

    +1

    Yeniden silmeyi, programlanmamış iş parçacığı havuzu yürütücüler için hala yararlı görünüyor. –

    0

    sizin ScheduledThreadPoolExecutor bir istisnası atılır eğer görevlerden herhangi birini çağırabilir sınıf statik bir olay eklemeyi düşünün. Bu şekilde, iş parçanızda gerçekleşen istisnaları yakalamak ve ele almak için bu etkinliği kullanabilirsiniz.

    +1

    'ScheduledThreadPoolExecutor'' java.util.concurrent' içinde ... – whiskeysierra

    5

    Futureget() yöntemini, scheduleAtFixedRate() numaralı telefonu arayarak kullanabilirsiniz. İş parçacığı yürütme sırasında bir yürütme oluştuğunda ExecutionException atar.

    +0

    Bu daha sonraki çağrılar için nasıl çalışır? Örneğin. Birincisi başarılı bir şekilde geri döndükten sonra ikinci giriş için nasıl bir gelecek elde edersiniz? –

    +0

    @Mark Bir yürütme başarısız olursa, ikinci (veya üçüncü, ...) yürütme olmayacaktır. Orijinal javadoc'tan kopyalandı: * Görevin herhangi bir yürütmesi bir istisna ile karşılaşırsa, sonraki infazlar bastırılır. * – whiskeysierra

    +0

    @Willi: O zaman OP'nin deyimiyle ilgili kafam karışmış sanırım "eğer istisnalar yiyorsa ..." sadece bir kez koşar. –

    2

    Ayrıca, Spring Framework numaralı telefondan ThreadPoolTaskScheduler, hata işleyiciyi ayarlamak için bir yöntem ortaya koyar ve sizin için tüm kaydırma işlemini gerçekleştirebilirsiniz. Varsayılan davranış, göreve göre değişir:

    Verilen ErrorHandler boş değilse, kullanılacaktır. Aksi takdirde, yinelenen görevler varsayılan olarak bastırılırken, tek vuruşlu görevler varsayılan olarak yayılan hatalara sahip olur, çünkü bu hatalar döndürülen Future aracılığıyla beklenebilir. Her iki durumda da, hatalar günlüğe kaydedilir.

    sadece sarma kısmını değil TaskScheduler kullanmak istiyorsanız TaskScheduler kullandığı bilgileri içermektedir

    TaskUtils.decorateTaskWithErrorHandler(task, errorHandler, isRepeatingTask) 
    

    kullanabilirsiniz.

    2

    ScheduledThreadPoolExecutor alt sınıfını ve gönderdiğiniz tüm Runnable'lar için istisnaları ve hataları işlemek için afterExecute yöntemini geçersiz kılabilirsiniz.