开启线程很容易,但是用户可能随时取消任务,怎么样让跑起来的线程正确地结束呢?
一个很容易想到的办法是,设置一个状态变量isCannelled,然后通过while(!isCannelled),执行循环体中的语句。如果某个时刻想中断线程,可以通过某个方法将isCannelled设置为true。但是这样做有一个缺点,就是如果线程一直处于阻塞状态,那么它根本执行不了isCancelled的检查。
java多线程提供了中断机制,interrupt(),isInterrupted(),interrupted()
每个线程都有一个boolean类型的中断状态,表示该线程是否中断,默认为false,当调用interrupt()方法时,会将该变量改为true.调用了线程的interrupt()方法后,并不会真正中断正在运行的线程,只是发出一个请求,由线程在合适时候结束自己。
isInterrupted()方法用于判断状态变量,如果有其他线程调用了interrupt()方法,那么isInterrupted()返回true,且不会重置。
return true if the current thread has been interrupted
也就是isInterrupted()和interrupted()方法都用于判断当前线程的中断状态,差别是一个不会reset状态,一个会reset状态。
当线程处于阻塞状态(Sleep(),wait())时,如果调用了interrupt()方法,线程会抛出InterruptedException,一旦抛出异常,线程状态就会重置,所以必须处理该异常,否则线程的中断状态还是会还原为false.
例如上面这段代码,如果其它线程调用了该线程的cannel()方法,而恰好该线程处于Sleep状态,就会抛出异常,如果不重新调用interrupt()方法,线程是不会结束的。
JUC中也提供了一些类库来实现中断,但是更好更强大。ExecutorService.submit()返回了Future对象来描述一个线程任务,Future有一个cancel()方法用于取消任务的执行。