Java多线程异常抛出后的表现及捕获

一、多线程抛出异常后并不影响主线程及其他子线程的正常执行

	public static void main(String[] args) {
		System.out.println("Main Thread start");
		Thread t1 = new Thread(new Runnable() {
			@Override
			public void run() {
				int i = 0;
				while(i<7) {
					System.out.println("Thread1 i: "+(i++));
					try {
						Thread.sleep(1000);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}

					if (i == 3) {
						throw new RuntimeException();
					}
				}
			}
		});
		Thread t2 = new Thread(new Runnable() {

			@Override
			public void run() {
				int i = 0;
				while(i<7) {
					System.out.println("Thread2 i: "+(i++));
					try {
						Thread.sleep(1000);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			}
		});



		t2.start();
		t1.start();


		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("Main Thread end");
	}

运行结果

Main Thread start
Thread2 i: 0
Thread1 i: 0
Main Thread end
Thread1 i: 1
Thread2 i: 1
Thread1 i: 2
Thread2 i: 2
Exception in thread "Thread-0" java.lang.RuntimeException
	at cc.eslink.safecheck.domain.dto.req.ProblemReq$1.run(ProblemReq.java:136)
	at java.lang.Thread.run(Thread.java:748)
Thread2 i: 3
Thread2 i: 4
Thread2 i: 5
Thread2 i: 6

Process finished with exit code 0

二、多线程抛出异常主线程无法捕获

public static void main(String[] args) {
	System.out.println("Main Thread start");
	Thread t1 = new Thread(new Runnable() {
		@Override
		public void run() {
			int i = 0;
			while(i<7) {
				System.out.println("Thread1 i: "+(i++));
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}

				if (i == 3) {
					throw new RuntimeException();
				}
			}
		}
	});
	Thread t2 = new Thread(new Runnable() {

		@Override
		public void run() {
			// TODO Auto-generated method stub
			int i = 0;
			while(i<7) {
				System.out.println("Thread2 i: "+(i++));
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	});


	t2.start();
	try{
		t1.start();
	}catch (RuntimeException e){
		System.out.println("异常捕获");
		e.printStackTrace();
	}


	try {
		Thread.sleep(1000);
	} catch (InterruptedException e) {
		e.printStackTrace();
	}
	System.out.println("Main Thread end");


}

运行结果

Main Thread start
Thread2 i: 0
Thread1 i: 0
Main Thread end
Thread2 i: 1
Thread1 i: 1
Thread1 i: 2
Thread2 i: 2
Thread2 i: 3
Exception in thread "Thread-0" java.lang.RuntimeException
	at cc.eslink.safecheck.domain.dto.req.ProblemReq$1.run(ProblemReq.java:136)
	at java.lang.Thread.run(Thread.java:748)
Thread2 i: 4
Thread2 i: 5
Thread2 i: 6

Process finished with exit code 0

三、捕获异常
Thread.UncaughtExceptionHandler是当线程因未捕获的异常而突然终止时调用的处理程序接口。

当一个线程由于未捕获的异常而即将终止时,Java虚拟机将使用它来 查询线程的 UncaughtExceptionHandler Thread.getUncaughtExceptionHandler(),并将调用该处理程序的 uncaughtException方法,并将该线程和异常作为参数传递。如果某个线程没有 显式设置其UncaughtExceptionHandler,则其ThreadGroup对象将充当其 UncaughtExceptionHandler。如果ThreadGroup对象没有处理异常的特殊要求,它可以将调用转发到默认的未捕获异常处理程序。

public static void main(String[] args) {
	System.out.println("Main Thread start");
	Thread t1 = new Thread(new Runnable() {
		@Override
		public void run() {
			int i = 0;
			while(i<7) {
				System.out.println("Thread1 i: "+(i++));
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}

				if (i == 3) {
					throw new RuntimeException();
				}
			}
		}
	});
	Thread t2 = new Thread(new Runnable() {

		@Override
		public void run() {
			// TODO Auto-generated method stub
			int i = 0;
			while(i<7) {
				System.out.println("Thread2 i: "+(i++));
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	});

	Thread.UncaughtExceptionHandler handler = new Thread.UncaughtExceptionHandler() {
		public void uncaughtException(Thread th, Throwable ex) {
			System.out.println("Uncaught exception: " + ex);
		}
	};

	t2.start();
	t1.setUncaughtExceptionHandler(handler);
	t1.start();


	try {
		Thread.sleep(1000);
	} catch (InterruptedException e) {
		e.printStackTrace();
	}
	System.out.println("Main Thread end");

}

运行结果

Main Thread start
Thread2 i: 0
Thread1 i: 0
Main Thread end
Thread1 i: 1
Thread2 i: 1
Thread2 i: 2
Thread1 i: 2
Thread2 i: 3
Uncaught exception: java.lang.RuntimeException
Thread2 i: 4
Thread2 i: 5
Thread2 i: 6

Process finished with exit code 0

四 线程池中异常捕获

1、execute方法,子线程中有异常会抛出异常;

 public static void main(String[] args) {
     ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(2, 5, 1000, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(10));
for (int i=0;i<10;i++) {
    threadPoolExecutor.execute(()->doTask("execute"));
    
}

 threadPoolExecutor.shutdown();

 }
 private static void doTask(String string)throws RuntimeException {
     String str = "ThreadName:"+ Thread.currentThread().getName()+"执行方式:"+string;
     System.out.println(str);
     List list = null;
     System.out.println(list.size());      

 }

2、submit方法,子线程中有异常不会抛出,需要使用future.get()方法获取异常信息;

public class ThreadPools {
    public static void main(String[] args) {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(2, 5, 1000, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(10));
   for (int i=0;i<10;i++) {
       Future future =  threadPoolExecutor.submit(()->doTask("submit"));
       try {
           future.get();
       } catch (InterruptedException e) {
           e.printStackTrace();
       } catch (ExecutionException e) {
           e.printStackTrace();
       }
   }

    threadPoolExecutor.shutdown();

    }
    private static void doTask(String string)throws RuntimeException {
        String str = "ThreadName:"+ Thread.currentThread().getName()+"执行方式:"+string;
        System.out.println(str);
        List list = null;
        System.out.println(list.size());
       /* try {
            System.out.println(list.size());
        }catch (Exception e) {
            System.out.println(e.getMessage());
        }
*/

    }
}

但是如果子线程中异常在子线程中被捕获到没有抛出,future.get()方法不会获取到异常信息;

public class ThreadPools {
    public static void main(String[] args) {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(2, 5, 1000, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(10));
   for (int i=0;i<10;i++) {
       Future future =  threadPoolExecutor.submit(()->doTask("submit"));
       try {
           future.get();
       } catch (InterruptedException e) {
           e.printStackTrace();
       } catch (ExecutionException e) {
           e.printStackTrace();
       }
   }

    threadPoolExecutor.shutdown();

    }
    private static void doTask(String string)throws RuntimeException {
        String str = "ThreadName:"+ Thread.currentThread().getName()+"执行方式:"+string;
        System.out.println(str);
        List list = null;
        
        try {
            System.out.println(list.size());
        }catch (Exception e) {
            System.out.println(e.getMessage());
        }

    }

你可能感兴趣的:(面试,多线程,java)