线程如何停止?线程之间如何协作?线程之间的异常如何处理? _
stop 方法虽然可以停止线程,但它已经是不建议使用的废弃方法了,这一点可以通过 Thread 类中的源码发现,stop 源码如下:
stop 方法是被 @Deprecated 修饰的不建议使用的过期方法,并且在注释的第一句话就说明了 stop 方法为非安全的方法。
原因在于它在终止一个线程时会强制中断线程的执行,不管run方法是否执行完了,并且还会释放这个线程所持有的所有的锁对象。这一现象会被其它因为请求锁而阻塞的线程看到,使他们继续向下执行。这就会造成数据的不一致。
比如银行转账,从A账户向B账户转账500元,这一过程分为三步,第一步是从A账户中减去500元,假如到这时线程就被stop了,那么这个线程就会释放它所取得锁,然后其他的线程继续执行,这样A账户就莫名其妙的少了500元而B账户也没有收到钱。这就是stop方法的不安全性。
设置标志位
如果线程的run方法中执行的是一个重复执行的循环,可以提供一个标记来控制循环是否继续
java
class FlagThread extends Thread { // 自定义中断标识符 public volatile boolean isInterrupt = false; @Override public void run() { // 如果为 true -> 中断执行 while (!isInterrupt) { // 业务逻辑处理 } } }但自定义中断标识符的问题在于:线程中断的不够及时。因为线程在执行过程中,无法调用 while(!isInterrupt) 来判断线程是否为终止状态,它只能在下一轮运行时判断是否要终止当前线程,所以它中断线程不够及时,比如以下代码:
java
class InterruptFlag { // 自定义的中断标识符 private static volatile boolean isInterrupt = false; public static void main(String[] args) throws InterruptedException { // 创建可中断的线程实例 Thread thread = new Thread(() -> { while (!isInterrupt) { // 如果 isInterrupt=true 则停止线程 System.out.println("thread 执行步骤1:线程即将进入休眠状态"); try { // 休眠 1s Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("thread 执行步骤2:线程执行了任务"); } }); thread.start(); // 启动线程 // 休眠 100ms,等待 thread 线程运行起来 Thread.sleep(100); System.out.println("主线程:试图终止线程 thread"); // 修改中断标识符,中断线程 isInterrupt = true; } }输出:我们期望的是:线程执行了步骤 1 之后,收到中断线程的指令,然后就不要再执行步骤 2 了,但从上述执行结果可以看出,使用自定义中断标识符是没办法实现我们预期的结果的,这就是自定义中断标识符,响应不够及时的问题。
interrupted中断
这种方式需要在while循环中判断使用
使用 interrupt 方法可以给执行任务的线程,发送一个中断线程的指令,它并不直接中断线程,而是发送一个中断线程的信号,把是否正在中断线程的主动权交给代码编写者。相比于自定义中断标识符而然,它能更及时的接收到中断指令,如下代码所示:
java
public static void main(String[] args) throws InterruptedException { // 创建可中断的线程实例 Thread thread = new Thread(() -> { while (!Thread.currentThread().isInterrupted()) { System.out.println("thread 执行步骤1:线程即将进入休眠状态"); try { // 休眠 1s Thread.sleep(1000); } catch (InterruptedException e) { System.out.println("thread 线程接收到中断指令,执行中断操作"); // 中断当前线程的任务执行 break; } System.out.println("thread 执行步骤2:线程执行了任务"); } }); thread.start(); // 启动线程 // 休眠 100ms,等待 thread 线程运行起来 Thread.sleep(100); System.out.println("主线程:试图终止线程 thread"); // 修改中断标识符,中断线程 thread.interrupt(); }输出:
