8

ThreadPoolExecutor#afterExecute() yönteminde çalışan iş parçacıklarının attığı istisnaları işlemek istiyorum. Ben kodu çalıştırırsanız ben çıktısını almakThreadPoolExecutor'ın afterExecute() işlevinde neden istisna sıfırdır?

public class MyExecutor extends ThreadPoolExecutor { 

    public static void main(String[] args) { 
     MyExecutor threadPool = new MyExecutor(); 
     Task<Object> task = new Task<>(); 
     threadPool.submit(task); 
    } 

    public MyExecutor() { 
     super(4, 20, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<>(4000)); 
    } 

    @Override 
    protected void afterExecute(Runnable r, Throwable t) { 
     super.afterExecute(r, t); 
     System.out.println("in afterExecute()"); 
     if (t != null) { 
      System.out.println("exception thrown: " + t.getMessage()); 
     } else { 
      System.out.println("t == null"); 
     } 
    } 

    private static class Task<V> implements Callable<V> { 

     @Override 
     public V call() throws Exception { 
      System.out.println("in call()"); 
      throw new SQLException("testing.."); 
     } 
    } 
} 

:

in call() 
in afterExecute() 
t == null 

Neden afterExecute() parametre Throwable tnull olduğu anda bu kod var? SQLException örneği olmasın mı?

cevap

7

Bu aslında beklenen bir davranıştır.

boş olmayan ise, Throwable yürütme aniden sona erdirmek neden yakalanmamış RuntimeException veya Hata olup:

afterExecute Javadoc teklif.

Bu throwable örneği RuntimeException veya Error, Exception işaretlenmemiş olacağı anlamına gelir. SQLException kontrol edilmiş bir istisna olduğundan, afterExecute'a aktarılmaz.

(hala Javadoc alıntı) başka bir şey oluyor burada da vardır:

Not: eylemler görevler (örneğin FutureTask gibi) açık bir şekilde veya böyle bu, teslim olarak yöntemlerle içine alınmışsa Görev nesneleri hesaplama istisnalarını yakalar ve sürdürürler ve böylece aniden sonlandırmaya neden olmazlar ve iç istisnalar bu yönteme aktarılmaz. Eğer bir Callable gönderiyorsunuz beri örnekte

, görev FutureTask içine alınır, bu nedenle bu durumda bulunmaktadır. Sizde bile RuntimeException kodunu atmak için kodunuzu değiştiriniz, afterExecute'a verilmeyecektir.

protected void afterExecute(Runnable r, Throwable t) { 
    super.afterExecute(r, t); 
    if (t == null && r instanceof Future) { 
     try { 
     Object result = ((Future) r).get(); 
     } catch (CancellationException ce) { 
      t = ce; 
     } catch (ExecutionException ee) { 
      t = ee.getCause(); 
     } catch (InterruptedException ie) { 
      Thread.currentThread().interrupt(); // ignore/reset 
     } 
    } 
    if (t != null) 
     System.out.println(t); 
} 
+0

Bunu temizlediğiniz için teşekkür ederiz. Yani kontrol edilen istisnalar sadece ThreadPoolExecutor tarafından yutulacak mı? Ve tüm istisna işleme Callable # call() içinde yapılmalıdır? –

+1

@ potato300 Düzenlemem görün, özel örneğinizde başka bir şey var (önce ben fark etmedim) – Tunaki

1

Bu bunu yapmanın alternatif bir yoludur: Javadoc Ben başvuru için, buraya taklit ediyorum bu başa bir örnek kod verir. here

package com.autonomy.introspect.service; 

import java.sql.SQLException; 
import java.util.concurrent.*; 

public class MyExecutor extends ThreadPoolExecutor { 

    public static void main(String[] args) { 
     MyExecutor threadPool = new MyExecutor(); 
     Task<Object> task = new Task<Object>(); 
     Future<Object> futureTask = threadPool.submit(task); 
     try { 
      System.out.println(futureTask.get()); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } catch (ExecutionException e) { 
      System.out.println("exception thrown: " + e.getMessage()); 
     } 
    } 

    public MyExecutor() { 
     super(4, 20, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(4000)); 
    } 

    @Override 
    protected void afterExecute(Runnable r, Throwable t) { 
     super.afterExecute(r, t); 
     System.out.println("in afterExecute()"); 
     if (t != null) { 
      System.out.println("exception thrown: " + t.getMessage()); 
     } else { 
      System.out.println("t == null"); 
     } 
    } 

    private static class Task<V> implements Callable<V> { 

     @Override 
     public V call() throws Exception { 
      System.out.println("in call()"); 
      throw new SQLException("testing.."); 
     } 
    } 
} 

den afterExecute kullanımını ipucu alınması farklı bir amaç içindir. Sırayla başarısız ve aniden sonlandırır.

İlgili konular