Estoy usando Callable y ExecutorService para usar subprocesos múltiples en mi aplicación.
En caso de que se produzcan excepciones desde un subproceso, debe detener todos los subprocesos aunque se haya completado el trabajo y deba arrojar esa excepción al método de clase de llamada. Para esto, utilicé un método shutDownNow().
¿Es este el camino correcto? o cualquier otra forma efectiva allí?
ExecutorService exSvc = Executors.newFixedThreadPool(5); exSvc.setKeepAliveTime(60, TimeUnit.SECONDS); List<Future<Integer>> futureList = new LinkedList(); for(int i=0; i<50;i++){ futureList.add(exSvc.submit( new Callable<Integer>() { public Integer call() throws Exception{ int num = new Random().nextInt(1000); if(num==500){ throw new Exception("Error"); } return num; } })); } for(int i=0; i<50; i++){ try { int value = futureList.get(i).get(); } catch (Exception e) { exSvc.shutdownNow(); throw new Exception("Error"); } }Esto debería funcionar en tu ejemplo. Sin embargo, asegúrese de manejar adecuadamente las interrupciones de subprocesos en sus invocables.
Tenga en cuenta que las otras tareas se cancelarán en la medida de lo posible y solo después de que haya notado que una de las tareas ha generado una excepción. Por ejemplo, si la tarea no. 5 ha lanzado una excepción, tiene que esperar a que se completen las tareas 0-4, y solo entonces se da cuenta de que la tarea 5 ha fallado.
Alternativamente, podría crear una subclase de ThreadPoolExecutor como aquí , para detectar la excepción lo antes posible.
Como dijo ciamei, si desea detectar la excepción lo antes posible, tal vez pueda usar un CountDownLatch :
CountDownLatch cdl = new CountDownLatch(1); AtomicInteger successCount = new AtomicInteger(); AtomicBoolean fail = new AtomicBoolean(); int taskSize = 50; for(int i=0; i<taskSize;i++){ futureList.add(exSvc.submit(new Callable<Integer>() { @Override public Integer call() throws Exception { int num = new Random().nextInt(1000); if(num == 500){ fail.set(true); cdl.countDown(); throw new Exception("Error"); } if (successCount.incrementAndGet() == taskSize) { cdl.countDown(); } return num; } })); } try { cdl.await(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } if (fail.get()) { exSvc.shutdownNow(); throw new Exception("Error"); } //...