18

내 코드는 않습니다 이하는 Future.get() 던져 ExecutionException 또는 예외 : InterruptedException

ExecutorService executor = Executors.newSingleThreadExecutor(); 
try { 
    Task t = new Task(response,inputToPass,pTypes,unit.getInstance(),methodName,unit.getUnitKey()); 
    Future<SCCallOutResponse> fut = executor.submit(t); 
    response = fut.get(unit.getTimeOut(),TimeUnit.MILLISECONDS); 
} catch (TimeoutException e) { 
    // if the task is still running, a TimeOutException will occur while fut.get() 
    cat.error("Unit " + unit.getUnitKey() + " Timed Out"); 
    response.setVote(SCCallOutConsts.TIMEOUT); 
} catch (InterruptedException e) { 
    cat.error(e); 
} catch (ExecutionException e) { 
    cat.error(e); 
} finally { 
    executor.shutdown(); 
} 

어떻게 코드의 InterruptedExceptionExecutionException 처리해야합니까?

그리고 어떤 경우에 이러한 예외가 발생합니까?

답변

27

ExecutionException과 InterruptedException은 매우 다른 두 가지입니다.

ExecutionException은 실행중인 스레드가 던져 버린 예외를 래핑하므로 스레드가 IOException을 발생시키는 IO를 발생시키는 인스턴스의 경우 ExecutionException에 래핑되어 재실행됩니다.

InterruptedException은 잘못된 것의 표시가 아닙니다. 멈출 때가되면 현재 작업을 끝내고 정상적으로 종료 할 수 있도록 스레드에게 알려주는 방법을 제공합니다. 내 응용 프로그램의 실행을 멈추기를 원하지만 스레드가 무언가를 처리하는 것을 원하지 않는다고 가정 해 봅시다 (데몬 스레드를 만들면 어떻게 될지). 그래서 응용 프로그램이 종료 될 때 내 코드는이 스레드에서 인터럽트 플래그를 설정하는 인터럽트 메서드를 호출하고 다음 번 스레드가 대기하거나 잠자기하면 인터럽트 플래그를 확인하고 사용할 수있는 InterruptedException을 throw합니다 스레드가 참여하는 무한 루프 프로세싱/슬리핑 로직에서 빠져 나오십시오. (스레드가 대기 또는 절전 모드가 아닌 경우 주기적으로 인터럽트 플래그를 확인할 수 있습니다.) 따라서 사용되는 예외의 인스턴스입니다 논리 흐름을 변경합니다. 당신이 그걸 전혀 로그 할 유일한 이유는 무슨 일이 일어나고 있는지, 아니면 인터럽트 논리가 제대로 작동하지 않는 문제를 디버깅하는 경우를 보여주는 예제 프로그램에있다.

+0

작업 처리 중 예외가 발생하면 ExecutionException이 throw되는 것을 방지 할 수있는 방법이 있습니까? 처리에서 Exception throws를 잡아서 처리하더라도 여전히 ExecutionException에 대한 예외를 래핑하고 get에 throw합니다. –

+0

InterruptedException과 ExecutionException 사이에 관계가 있으며, 어느 것이 먼저 catch되는지 알아야합니다. SO 질문에서 그는 InterruptedException을 먼저 catch 한 다음 ExecutionException을 catch합니다. 주문을 교환하면 문제는 동일합니까? – prime

+0

@prime : https://stackoverflow.com/a/10964899/217324를 참조하십시오. 두 예외 모두 예외를 확장하고 다른 예외보다 더 구체적이지 않습니다. 이 경우 주문은 중요하지 않습니다. –

6

InterruptedException 계산이 완료되기 전에 대기 스레드에서 interrupt이 호출되면 throw됩니다.

ExecutionException (이 경우 Task) 예외가 발생하면 예외가 발생합니다.

어떻게 처리 할 것인지는 전적으로 응용 프로그램에 따라 다릅니다.

편집 :

import java.util.concurrent.*; 

public class Test 
{ 
    public static void main(String[] args) throws Exception 
    { 
     ExecutorService executor = Executors.newFixedThreadPool(2); 
     Future<String> future = executor.submit(new SlowCallable()); 
     executor.submit(new Interruptor(Thread.currentThread())); 
     try 
     { 
      System.out.println(future.get()); 
     } 
     catch (InterruptedException e) 
     { 
      System.out.println("I was interrupted"); 
     } 
    } 

    private static class Interruptor implements Callable<String> 
    { 
     private final Thread threadToInterrupt; 

     Interruptor(Thread threadToInterrupt) 
     { 
      this.threadToInterrupt = threadToInterrupt; 
     } 

     public String call() throws Exception 
     { 
      Thread.sleep(2000); 
      threadToInterrupt.interrupt(); 
      return "interrupted other thread"; 
     } 
    } 

    private static class SlowCallable implements Callable<String> 
    { 
     public String call() throws Exception 
     { 
      Thread.sleep(5000); 
      return "finished"; 
     } 
    } 
} 
+0

내가 Thread.interrupt()를 호출하면 인터럽트 플래그가 true로 설정됩니다. 그러나 InterruptedException이 throw되지 않습니다. –

+0

검사되지 않은 예외 일 필요는 없습니다. 'Callable.call()'은 무엇이든 던질 수 있습니다. – finnw

+0

@finnw : 맞습니다. 그것을 놓쳐서 미안. –

3

IBM의 개발자는 기사 Dealing with InterruptedExceptionInterruptedException을 처리하는 방법에 대한 몇 가지 조언을 가지고 작품 : 여기에 중단되는 데모가 있습니다.

-1

세 가지 유형의 예외를 반환하는 샘플 코드.

import java.util.concurrent.*; 
import java.util.*; 

public class ExceptionDemo{ 
    public static void main(String args[]){ 
     int poolSize=1; 
     int maxPoolSize=1; 
     int queueSize=30; 
     long aliveTive=60; 
     ArrayBlockingQueue<Runnable> queue= new ArrayBlockingQueue<Runnable>(queueSize); 
     ThreadPoolExecutor executor= new ThreadPoolExecutor(poolSize,maxPoolSize,aliveTive, 
         TimeUnit.MILLISECONDS,queue); 
     List<Future> futures = new ArrayList<Future>(); 
     for (int i=0; i < 5; i++){ 
      futures.add(executor.submit(new RunnableEx())); 
     } 
     for (Iterator it = futures.iterator(); it.hasNext();){ 
      try { 
       Future f = (Future)it.next(); 
       f.get(4000,TimeUnit.MILLISECONDS); 
      }catch(TimeoutException terr){ 
       System.out.println("Timeout exception"); 
       terr.printStackTrace(); 
      } 
      catch(InterruptedException ierr){ 
       System.out.println("Interrupted exception:"); 
       ierr.printStackTrace(); 
      }catch(ExecutionException err){ 
       System.out.println("Exeuction exception:"); 
       err.printStackTrace(); 
       Thread.currentThread().interrupt(); 
      } 
     } 
     executor.shutdown(); 
    } 
} 

class RunnableEx implements Runnable{ 
    public void run() { 
     // code in here 
     System.out.println("Thread name:"+Thread.currentThread().getName()); 
     try{ 
      Random r = new Random(); 
      if (r.nextInt(2) == 1){ 
       Thread.sleep(2000); 
      }else{ 
       Thread.sleep(4000); 
      } 
      System.out.println("eee:"+1/0); 
     }catch(InterruptedException irr){ 
      irr.printStackTrace(); 
     } 
    } 
} 

출력 :

Thread name:pool-1-thread-1 
Timeout exception 
Thread name:pool-1-thread-1 
java.util.concurrent.TimeoutException 
     at java.util.concurrent.FutureTask.get(FutureTask.java:201) 
     at ExceptionDemo.main(ExceptionDemo.java:20) 
Thread name:pool-1-thread-1 
Exeuction exception: 
java.util.concurrent.ExecutionException: java.lang.ArithmeticException:/by zero 
     at java.util.concurrent.FutureTask.report(FutureTask.java:122) 
     at java.util.concurrent.FutureTask.get(FutureTask.java:202) 
     at ExceptionDemo.main(ExceptionDemo.java:20) 
Caused by: java.lang.ArithmeticException:/by zero 
     at RunnableEx.run(ExceptionDemo.java:49) 
     at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471) 
     at java.util.concurrent.FutureTask.run(FutureTask.java:262) 
     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) 
     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) 
     at java.lang.Thread.run(Thread.java:744) 
Interrupted exception: 
java.lang.InterruptedException 
     at java.util.concurrent.FutureTask.awaitDone(FutureTask.java:400) 
     at java.util.concurrent.FutureTask.get(FutureTask.java:199) 
     at ExceptionDemo.main(ExceptionDemo.java:20) 
Timeout exception 
java.util.concurrent.TimeoutException 
     at java.util.concurrent.FutureTask.get(FutureTask.java:201) 
Thread name:pool-1-thread-1 
     at ExceptionDemo.main(ExceptionDemo.java:20) 
Thread name:pool-1-thread-1 
Timeout exception 
java.util.concurrent.TimeoutException 
     at java.util.concurrent.FutureTask.get(FutureTask.java:201) 
     at ExceptionDemo.main(ExceptionDemo.java:20) 

TimeoutException :시 차단 동작이 타임 아웃 발생 예외. 위의 예에서

, 일부 작업은 많은 시간 (4 초 인해 수면)을 고려하여 제한 시간을 증가 시키거나의 Runnable 작업을 최적화 어느 Future

get()의 작동을 차단한다.

ExecutionException : 예외 발생에 의해 중단 된 태스크의 결과를 취득하려고 => 계산 예외

위의 예에서

던질 때이 Exception 일반적 ArithmeticException:/by zero

통해 시뮬레이션 슬로우 예외 예제에서 인용 된 것처럼 사소한 것이라면 근본 원인을 수정해야합니다.

InterruptedException : 스레드가 대기 중이거나 대기 중이거나 점유 중이며 스레드가 활동 전이나 도중에 중단되면 발생합니다.

위의 예에서이 ExceptionExecutionException 동안 현재 스레드를 인터럽트하여 시뮬레이트됩니다.

일반적으로 잡아서는 안됩니다.

+0

@downvoter, 질문과 대답을 다시 확인하십시오. 자바의 공식 문서화 이유는 여기에 인용되어 있습니다. –

+0

InterruptedException과 ExecutionException 사이에 관계가 있으며, 어느 것이 먼저 catch되는지 알아야합니다. SO 질문에서 그는 InterruptedException을 먼저 catch 한 다음 ExecutionException을 catch합니다. 주문을 교환하면 문제는 동일합니까? – prime

+0

InterruuptedException을 먼저 catch해야합니다. –