In a Java multithreaded program, all threads are not allowed to throw uncaught checked exception (such as interruptedexception at Sleep), which means that each thread needs to own its own checked Exception Dispose of it. This is constrained by the Java.lang.Runnable.run () method declaration (because there is no throw exception part of this method declaration). However, threads can still throw unchecked exception (such as run-time exceptions), and when such exceptions run out, the thread will end up completely unaffected by the main thread and other threads, completely unaware of the exception that is thrown by one of the threads (which is also a complete inability to catch this exception). This design of the JVM stems from the idea that "threads are pieces of code that are executed independently, and that the thread's problem should be solved by the thread itself rather than being delegated to the outside." "Based on this design philosophy, in Java, the exception of threading methods (whether checked or unchecked exception) should be within the bounds of the thread code (inside the Run method) to try Catch and dispose of it. In other words, we can't catch an exception escaping from a thread.
Look at the following example:
Import Java.util.concurrent.executorservice;import Java.util.concurrent.executors;public class ExceptionThread Implements Runnable { @Override public void Run () { throw new RuntimeException ("This thread is doing one thing, throwing a runtime exception"); } public static void Main (string[] args) { try { Executorservice exec = Executors.newcachedthreadpool (); Exec.execute (New Exceptionthread ()); System.out.println ("Why do You Go"); } catch (RuntimeException e) { System.out.println ("Can I catch an exception?") "); } }}
Operation Result:
Why are you doing this? exception in thread "Pool-1-thread-1" Java.lang.RuntimeException: This thread is doing one thing, throwing a runtime exception at Exceptionthread.run (Exceptionthread.java:8) at Java.util.concurrent.threadpoolexecutor$worker.runtask ( threadpoolexecutor.java:886) at Java.util.concurrent.threadpoolexecutor$worker.run (ThreadPoolExecutor.java : 908) at Java.lang.Thread.run (thread.java:619)
From the running result, we can see that this exception is not caught in the main thread, i.e.
System.out.println ("Can I catch an exception?") ");
Will never execute to.
The question is, what should we do if we need to capture the unchecked exception of its thread? After Java SE5, we can solve this problem by executor. To solve this problem, we need to modify the way executor generates threads. Thread.uncaughtexceptionhandler is a new interface in Java SE5 that allows us to add an exception handler on each of the thread objects. (Uncaughtexceptionhandler). The Thread.UncaughtExceptionHandler.uncaughtException () method is called when the thread is facing death from an uncaught exception. The following example simply demonstrates how to use the Uncaughtexceptionhandler
public class
ExceptionThread2
implements
Runnable {
@Override
public
void
run() {
Thread t = Thread.currentThread();
System.out.println(
"run() by"
+ t);
System.out.println(
"eh="
+ t.getUncaughtExceptionHandler());
throw
new
RuntimeException(
"抛出运行时异常"
);
}
}
|
Import java.lang.thread.uncaughtexceptionhandler;/** * For catching exceptions---capturing uncheckedexception * * @author february30th * */public class Myunchecckedexceptionhandler implements Uncaughtexceptionhandler { @Override public Void Uncaughtexception (Thread T, Throwable e) { System.out.println ("Catch to Exception:" + e);} }
Import Java.util.concurrent.threadfactory;public class Handlerthreadfactory implements Threadfactory { @Override Public thread Newthread (Runnable r) { System.out.println ("Create a new Thread"); Thread t = new Thread (r); T.setuncaughtexceptionhandler (New Myunchecckedexceptionhandler ()); System.out.println ("eh121 =" + T.getuncaughtexceptionhandler ()); return t; }}
Import Java.util.concurrent.executorservice;import Java.util.concurrent.executors;public class ThreadExceptionTest {/** * @param args */public static void main (string[] args) {////below There are 3 ways to execute a thread. The 1th kind is in the normal way. This is the ability to catch an exception thread t = new Thread (new ExceptionThread2 ()); T.setuncaughtexceptionhandler (New Myunchecckedexceptionhandler ()); T.start (); The 2nd kind according to the off-the-shelf pool, directly according to Thread way, at this time cannot catch the exception, why? Because a thread is created in the code below, and the exception handler is set,///However, the new thread object is reset in our thread pool, and the thread object does not have any exception handler set, in other words, any operations that are done on the thread outside of our online pool are useless Executorservice EXEC1 = Executors.newcachedthreadpool (); Runnable Runnable = new ExceptionThread2 (); thread T1 = new Thread (runnable); T1.setuncaughtexceptionhandler (New Myunchecckedexceptionhandler ()); Exec1.execute (runnable); The 3rd situation is the same as the thread pool, but it is through the threadfactory way, in the threadfactory will do some control of the thread, you can set the exception handler//At this time can catch the exception. Executorservice exec = Executors.newcachedthreadpool (new HAndlerthreadfactory ()); Exec.execute (New ExceptionThread2 ()); }}
Run results
Create a new thread eh121 = [email protected]run () Bythread[thread-0,5,main][email protected] Catch to exception: Java.lang.RuntimeException: Throwing run-time exceptions
As you can see from the running results above, uncaught exceptions are captured by Uncaughtexception.
According to the above example, we can set the processor one by one according to the specific situation. But if we know that we are going to use the same exception handler everywhere in the code, the simpler way is to set a static domain in the thread class and set the processor as the default uncaught exception handler. Look at the following example:
Thread.setdefaultuncaughtexceptionhandler (New Myunchecckedexceptionhandler ()); Executorservice exec = Executors.newcachedthreadpool (new handlerthreadfactory ()); Exec.execute (New ExceptionThread2 ());
This default processor is called only if the thread does not have a non-default exception handler. At runtime, the system checks to see if the thread has its own exception handler, and if not, checks to see if the appropriate thread group has a proprietary exception handler, and if not, calls the default exception handler.
Excerpt from: http://www.cnblogs.com/chenfei0801/archive/2013/04/23/3039286.html
Exception capture in JAVA threads