线程 - 这段危险代码90%的人都写过!

最近一个同学发来消息说,公司里有一段代码使用的线程经常会发生一些莫名其妙的问题。让我帮忙看看,我仔细看了很多遍线程的相关代码。最后注意到了 InterruptException 异常,把想法和 demo 代码给他说了后,问题果真被解决了。

关于这个问题,我通过一段简化的代码来给大家演示一下。

线程 - 这段危险代码90%的人都写过!

看到上面这段 demo 了吗?多简单,多熟悉啊。但是有一个问题,90% 的人可能都没有遇到,但确实存在的。

我们先看 Thread.sleep 为什么要抛出一个异常?其实,很简单,你仔细想想,如果你正在睡觉的时候,突然有人打扰到你,是不是就相当于发生了中断睡觉的异常。而 InterruptedException 这个异常的发生就是因为有人打扰了这个线程的休眠。

谁打扰的呢?就是调用这个线程的 interrupt() 方法的对象。OK ,现在我们来看看,当我调用上面这个线程的 interrupt() 方法的时候,它正在休眠,那么就会发生 InterruptedException 异常。而这个时候,你却把 InterruptedException 异常捕捉了,于是本该停止的线程就行失去刹车的车辆一样裸奔了。

而正确的处理 InterruptedException 异常的方法是,捕捉异常之后,加一个 break,终止线程。除此之外,结束一个线程推荐的方法有 3 种。

线程 - 这段危险代码90%的人都写过!

现在我们再来看看为什么 Thread.stop、Thread.suspend、Thread.resume、Runtime.runFinalizersOnExit 这几个方法都被废弃了。这是因为,这几个操作太暴力了。stop() 方法会真的杀死线程,不给线程喘息的机会,如果线程持有 ReentrantLock 锁,被 stop() 的线程并不会自动调用 ReentrantLock 的 unlock() 去释放锁,那其他线程就再也没机会获得 ReentrantLock 锁,这实在是太危险了。所以该方法就不建议使用了,类似的方法还有 suspend() 和 resume() 方法、Runtime.runFinalizersOnExit() 方法,这 3 个方法同样也都不建议使用了。危害性都非常大,所以被废弃的方法你千万不要使用!