一、多线程抛出异常后并不影响主线程及其他子线程的正常执行
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());
}
}