문제

다음 코드가 있다고 말합니다.

ExecutorService executor = Executors.newSingleThreadExecutor();
executor.execute(myRunnable);

이제 myRunnable 던지는 a RuntimeExcpetion, 어떻게 잡을 수 있습니까? 한 가지 방법은 내 자신을 공급하는 것입니다 ThreadFactory 구현 newSingleThreadExecutor() 그리고 사용자 정의를 설정하십시오 uncaughtExceptionHandlers에 대한 s Thread그것에서 나오는 s. 또 다른 방법은 포장하는 것입니다 myRunnable 현지 (익명) Runnable 여기에는 try -catch -block이 포함되어 있습니다. 어쩌면 다른 유사한 해결 방법도있을 수 있습니다. 그러나 ... 어떻게 든 이것은 더러워진 느낌이 든다. 나는 그것이 복잡하지 않아야한다고 생각한다. 깨끗한 솔루션이 있습니까?

도움이 되었습니까?

해결책

깨끗한 해결 방법은 사용하는 것입니다 ExecutorService.submit() 대신에 execute(). 이것은 당신을 반환합니다 Future 작업의 결과 또는 예외를 검색하는 데 사용할 수 있습니다.

ExecutorService executor = Executors.newSingleThreadExecutor();
Runnable task = new Runnable() {
  public void run() {
    throw new RuntimeException("foo");
  }
};

Future<?> future = executor.submit(task);
try {
  future.get();
} catch (ExecutionException e) {
  Exception rootException = e.getCause();
}

다른 팁

런타임 예외를 포착하고 처리 할 수있는 다른 런 가능하게 달리기를 장식하십시오.

public class REHandler implements Runnable {
    Runnable delegate;
    public REHandler (Runnable delegate) {
        this.delegate = delegate;
    }
    public void run () {
        try {
            delegate.run ();
        } catch (RuntimeException e) {
            ... your fancy error handling here ...
        }
    }
}

executor.execute(new REHandler (myRunnable));

전화하지 않겠습니까? ExecutorService#submit(), 얻으십시오 Future 뒤로 그리고 전화 할 때 가능한 예외를 직접 처리하십시오 Future#get() ?

Skaffman은 그 사용에서 정확합니다 submit 가장 깨끗한 접근법입니다. 대안적인 접근법은 서브 클래스입니다 ThreadPoolExecutor 그리고 무시합니다 afterExecute(Runnable, Throwable). 이 접근법을 따르는 경우 반드시 전화하십시오 execute(Runnable) 보다는 submit(Runnable) 또는 afterExecute 호출되지 않습니다.

API 설명에 따라 :

주어진 실행 가능의 실행이 완료되면 메소드가 호출되었습니다. 이 방법은 작업을 실행 한 스레드에 의해 호출됩니다. 널이 아닌 경우, 던질 수있는 사람은 잡을 수 없습니다 RuntimeException 또는 Error 이로 인해 실행이 갑자기 종료되었습니다.

참고 : 작업 (예 : FutureTask)에 작업이 명시 적으로 또는 제출과 같은 방법을 통해 동작이 밀폐 될 때, 이러한 작업 객체는 계산 예외를 포착하고 유지하므로 갑작스런 종결을 일으키지 않으며 내부 예외는 다음과 같습니다. 이 방법으로 전달되지 않았습니다.

작업(Callable 또는 Runnable) 제출 ThreadPoolExecutors a로 변환됩니다 FuturnTask, 이름이 지정된 소품이 포함되어 있습니다 callable 제출 한 작업과 같습니다. Futurntask에는 자체가 있습니다 run 다음과 같은 방법. 모든 예외 또는 던질 수있는 던지기 c.call() 붙잡아지고 이름이 지정된 소품에 넣을 것입니다 outcome. Futurntask를 호출 할 때 get 방법, outcome 던질 것입니다

JDK1.8 소스 코드에서 Futurntask.RUN

public void run() {
        ...
        try {
            Callable<V> c = callable;
            if (c != null && state == NEW) {
                V result;
                boolean ran;
                try {
                    result = c.call();
                    ran = true;
                } catch (Throwable ex) {
                    result = null;
                    ran = false;
                    // save ex into `outcome` prop
                    setException(ex);
                }
                if (ran)
                    set(result);
            }
        }
        ...
    }

예외를 잡으려면 :

      1. Skaffman의 대답
      2. ThreadPooleExecutor를 새로 사용하면`jectexecute '를 덮어 씁니다
        @Override
        protected void afterExecute(Runnable r, Throwable t) {
            super.afterExecute(r, t);
            Throwable cause = null;
            if (t == null && r instanceof Future) {
                try {
                    ((Future<?>) r).get();
                } catch (InterruptedException | ExecutionException e) {
                    cause = e;
                }
            } else if (t != null) {
                cause = t;
            }
            if (cause != null) {
                // log error
            }
        }
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top