我们知道,同一个进程中的多个线程共享进程资源,包括主内存、文件句柄、锁资源等。那么当一个线程死了(非正常退出、死循环等)就会导致线程该占有的资源永远无法释放,从而影响其他线程的正常工作,看下面一个例子。
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class ExceptInChildThread {
public static void main(String[] args){
Lock lock=new ReentrantLock(true);
Runnable taskRuntimeExcept= new Runnable() {
@Override
public void run() {
lock.lock();
int[] array = new int[2];
System.out.println(array[2]);
lock.unlock();
}
};
Thread threadRuntimeExcept = new Thread(taskRuntimeExcept);
threadRuntimeExcept.start();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
lock.lock();
System.out.println(i);
lock.unlock();
}
}
}).start();
}
}
输出:
Exception in thread "Thread-0" java.lang.ArrayIndexOutOfBoundsException: 2
at edu.whu.swe.lxl.learn.except.ExceptInChildThread$1.run(ExceptInChildThread.java:15)
at java.lang.Thread.run(Thread.java:748)
可以看到,第二个线程并没有执行下去。原因如下:
在第一个线程threadRuntimeExcept发生数组越界之后,线程异常没有捕获,导致线程异常退出。但是子线程的异常并不能传递到主线程(Runable的run方法没有任何throw),所以主线程仍然是可以运行的。问题在于,threadRuntimeExcept这个线程占有了lock这个锁,并在锁被释放之前异常退出了,那么这个锁就永远被占有了,等到第二个线程试图获取锁的时候,它就会一直阻塞在那。
Future虽然可以知道子线程发生了异常,但是却无法处理异常让子线程继续运行,子线程还是会异常退出。