Runnable의 run () 예외를 발생시키는 방법이 있습니까?
Runnable ) 을 구현하는 클래스의 run () 에서 호출하는 메서드 는 예외를 발생 시키도록 설계되었습니다.
그러나 Java 컴파일러는 그렇게 할 수 없으며 try / catch로 둘러싸라고 제안합니다.
문제는 그것을 try / catch로 둘러 싸서 특정 run ()을 쓸모 없게 만든다는 것 입니다 . 내가 할 그 예외를 throw합니다.
run () 자체에 throws
대해 지정 하면 컴파일러는 .Exception is not compatible with throws clause in Runnable.run()
보통 나는 run () 이 예외를 던지 도록 두지 않아도 괜찮습니다 . 하지만 그 기능이 있어야하는 독특한 상황이 있습니다.
이 제한을 어떻게 해결합니까?
당신이 구현하는 클래스를 전달하려는 경우 Runnable
에 Thread
프레임 워크, 당신은 그 프레임 워크의 규칙에 의해 놀이에이를, 그렇지 않으면 그 일을하는 것은 좋은 생각이 왜, 어니스트 프리드먼 - 힐의 답변을 참조하십시오.
그러나 run
코드에서 직접 메서드 를 호출 하여 호출 코드에서 예외를 처리 할 수 있다는 직감이 있습니다 .
이 문제에 대한 답은 간단합니다. Runnable
스레드 라이브러리의 인터페이스를 사용하지 말고 대신 확인 된 예외를 throw 할 수 있도록 수정 된 서명으로 자신의 인터페이스를 만듭니다.
public interface MyRunnable
{
void myRun ( ) throws MyException;
}
이 인터페이스를 Runnable
Thread 프레임 워크에서 사용하기에 적합한 실제 (checked exception 처리) 로 변환하는 어댑터를 만들 수도 있습니다 .
당신은을 사용할 수 있습니다 Callable
에 제출, 대신 ExecutorService
과 함께 결과를 기다리고 FutureTask.isDone()
에 의해 반환 ExecutorService.submit()
.
때 isDone()
true를 반환하면 전화 FutureTask.get()
. 당신은 지금, 만약 Callable
던져 않은는 Exception
다음 FutureTask.get()
을 던져 wiill Exception
도 원래 예외는 사용하여 액세스 할 수 있습니다 Exception.getCause()
.
run()
확인 된 예외를 던졌다 면 무엇이 그것을 잡을까요? run()
호출을 호출하는 코드를 작성하지 않기 때문에 해당 호출을 처리기에 포함시킬 방법이 없습니다.
run()
메서드 에서 확인 된 예외를 포착 RuntimeException
하고 그 자리에 체크 되지 않은 예외 (예 :)를 throw 할 수 있습니다 . 스택 추적으로 스레드를 종료합니다. 아마도 그것은 당신이 추구하는 것입니다.
대신 run()
메서드가 어딘가에 오류를보고하도록하려면 run()
메서드의 catch
블록을 호출 할 콜백 메서드를 제공하면 됩니다. 이 메서드는 예외 개체를 어딘가에 저장할 수 있으며 관심있는 스레드는 해당 위치에서 개체를 찾을 수 있습니다.
예, 메서드 에서 확인 된 예외 를 throw하는 run()
방법이 있지만 너무 끔찍해서 공유하지 않을 것입니다.
대신 할 수있는 작업은 다음과 같습니다. 런타임 예외가 실행하는 것과 동일한 메커니즘을 사용합니다.
@Override
public void run() {
try {
/* Do your thing. */
...
} catch (Exception ex) {
Thread t = Thread.currentThread();
t.getUncaughtExceptionHandler().uncaughtException(t, ex);
}
}
다른 사람들이 언급했듯이 run()
메서드가 실제로의 대상 Thread
이면 관찰 할 수 없기 때문에 예외를 throw 할 필요가 없습니다. 예외를 던지는 것은 예외를 던지지 않는 것과 같은 효과가 있습니다 (없음).
그것이 아니라면 Thread
대상, 사용하지 않습니다 Runnable
. 예를 들어, 아마도 Callable
더 적합합니다.
@FunctionalInterface
public interface CheckedRunnable<E extends Exception> extends Runnable {
@Override
default void run() throws RuntimeException {
try {
runThrows();
}
catch (Exception ex) {
throw new RuntimeException(ex);
}
}
void runThrows() throws E;
}
어떤 사람들은 당신이 규칙에 따라 플레이해야한다고 설득하려고합니다. 하지만 순종 여부는 상황에 따라 결정해야합니다. 현실은 "당신은 규칙에 따라 플레이해야한다"입니다 ( "규칙에 따라 플레이해야합니다"가 아닙니다). 규칙을 지키지 않으면 결과가 발생할 수 있습니다.
The situation not only applies in the situation of Runnable
, but with Java 8 also very frequently in the context of Streams and other places where functional interfaces have been introduced without the possibility to deal with checked exceptions. For example, Consumer
, Supplier
, Function
, BiFunction
and so on have all been declared without facilities to deal with checked exceptions.
So what are the situations and options? In the below text, Runnable
is representative of any functional interface that doesn't declare exceptions, or declares exceptions too limited for the use case at hand.
- You've declared
Runnable
somewhere yourself, and could replaceRunnable
with something else.- Consider replacing
Runnable
withCallable<Void>
. Basically the same thing, but allowed to throw exceptions; and has toreturn null
in the end, which is a mild annoyance. - Consider replacing
Runnable
with your own custom@FunctionalInterface
that can throw exactly those exceptions that you want.
- Consider replacing
- You've used an API, and alternatives are available. For example, some Java APIs are overloaded so you could use
Callable<Void>
instead ofRunnable
. - You've used an API, and there are no alternatives. In that case, you're still not out of options.
- You can wrap the exception in
RuntimeException
. - You can hack the exception into a RuntimeException by using an unchecked cast.
- You can wrap the exception in
You can try the following. It's a bit of a hack, but sometimes a hack is what we need. Because, whether an exception should be checked or unchecked is defined by its type, but practically should actually be defined by the situation.
@FunctionalInterface
public interface ThrowingRunnable extends Runnable {
@Override
default void run() {
try {
tryRun();
} catch (final Throwable t) {
throwUnchecked(t);
}
}
private static <E extends RuntimeException> void throwUnchecked(Throwable t) {
throw (E) t;
}
void tryRun() throws Throwable;
}
I prefer this over new RuntimeException(t)
because it has a shorter stack trace.
You can now do:
executorService.submit((ThrowingRunnable) () -> {throw new Exception()});
Disclaimer: The ability to perform unchecked casts in this way might actually be removed in future versions of Java, when generics type information is processed not only at compile time, but also at runtime.
I think a listener pattern might help you with this scenario. In case of an exception happening in your run()
method, use a try-catch block and in the catch send a notification of an exception event. And then handle your notification event. I think this would be a cleaner approach. This SO link gives you a helpful pointer to that direction.
Your requirement doesn't make any sense. If you want to notify the called of the thread about an exception that happened, you could do that through a call back mechanism. This can be through a Handler or a broadcast or whatever else you can think of.
The easiest way is to define your own exception object which extend the RuntimeException
class instead of the Exception
class.
참고URL : https://stackoverflow.com/questions/11584159/is-there-a-way-to-make-runnables-run-throw-an-exception
'Program Tip' 카테고리의 다른 글
요소의 배경색 코드를 얻는 방법은 무엇입니까? (0) | 2020.11.14 |
---|---|
문자열 비교 자바 스크립트 반환 가능성 % (0) | 2020.11.14 |
문자열이 같지 않은 경우 어떻게 비교합니까? (0) | 2020.11.14 |
100,000 개 이상의 개별 IP 주소를 차단하는 방법 (0) | 2020.11.14 |
Entity Framework 6.0에서 마이그레이션을 비활성화하는 방법 (0) | 2020.11.14 |