线程的终止stop与线程的中断interrupted
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线程的终止stop与线程的中断interrupted相关的知识,希望对你有一定的参考价值。
线程除了运行完毕,自动进入死亡状态,也可以手动进行停止,Thread类也提供了2个类方法来进行线程的停止。
一、stop
如图所示,stop方法已经被标记为过时的,不推荐的。因为这这个方法太过于暴力,会立即杀死进程,导致数据不能同步,带来很难排查的错误。
下面是一段造成错误信息的代码:
1 public class StopThreadUnsafe { 2 public static User u = new User(); 3 4 public static class User { 5 private int id; 6 private String name; 7 8 9 public User() { 10 this.id = 0; 11 this.name = "0"; 12 } 13 14 public int getId() { 15 return id; 16 } 17 18 public void setId(int id) { 19 this.id = id; 20 } 21 22 public String getName() { 23 return name; 24 } 25 26 public void setName(String name) { 27 this.name = name; 28 } 29 30 @Override 31 public String toString() { 32 return "User{" + 33 "id=" + id + 34 ", name=‘" + name + ‘\\‘‘ + 35 ‘}‘; 36 } 37 } 38 39 public static class ChangeObjectThread extends Thread { 40 volatile boolean stopme = false; 41 42 public void stopMe() { 43 stopme = true; 44 } 45 46 @Override 47 public void run() { 48 while (true) { 49 // if (stopme) { 50 // System.out.println("exit by stop me "); 51 // break; 52 // } 53 synchronized (u) { 54 int v = (int) (System.currentTimeMillis() / 1000); 55 u.setId(v); 56 //暂停一段时间 57 58 try { 59 Thread.sleep(100); 60 } catch (InterruptedException e) { 61 e.printStackTrace(); 62 } 63 //暂停之后再写入值 64 u.setName(String.valueOf(v)); 65 } 66 Thread.yield(); 67 } 68 } 69 } 70 71 public static class ReadObjectThread extends Thread { 72 @Override 73 public void run() { 74 while (true) { 75 synchronized (u) { 76 if (u.getId() != Integer.parseInt(u.getName())) { 77 System.out.println(u.toString()); 78 } 79 } 80 Thread.yield(); 81 } 82 } 83 } 84 85 86 public static void main(String[] args) throws InterruptedException { 87 new ReadObjectThread().start(); 88 while (true) { 89 Thread t = new ChangeObjectThread(); 90 t.start(); 91 Thread.sleep(150); 92 t.stop(); 93 } 94 } 95 }
运行起来的结果是:
里面情况是id和name是同一个值,但是被强行stop掉了线程,导致数据混乱。
那么如何停止一个线程呢?
在线程体中加一个flag,每次执行线程体时查看标杆,如果标杆有效,则自动退出,如代码中,就有一个stopme方法,在合适的时候调用就可以停止线程,而且是缓和的,基本上不会带来数据丢失的问题。
二、interrupt
stop既然这么坑,所有JDK还是给了解决办法的,那就是线程中断Interrupt。
JDK里面有4个关于interrupt的方法,
public void interrupt()
中断线程,该方法是一个实例方法,它通知目标线程中断,也就是设置中断标志位。,中断标志位标识当前线程已经被中断了。tips:给线程加了中断,并不会对线程起实质性作用,仅仅是设置了中断标志位,还需要进行一系列退出操作才可以进行线程的终止。public boolean isInterrupted()判断当前线程是否有被中断,通过检查中断标志位来判断。public static boolean interrupted()
interrupted也是用来判断当前线程的中断状态,但同时会清除当前能线程的中断标志位状态。private native boolean isInterrupted(boolean ClearInterrupted)
代码示例:
1 /** 2 * 关于中断Interrupt 3 * Created by huxingyue on 2017/9/3. 4 */ 5 public class InterruptAbout { 6 public static void main(String[] args) throws InterruptedException { 7 Thread t1 = new Thread() { 8 @Override 9 public void run() { 10 while (true) { 11 //这才是合理的退出 12 if (Thread.currentThread().isInterrupted()) { 13 System.out.println("here is interrupted "); 14 break; 15 } 16 System.out.println("这里执行了一次yield"); 17 18 System.out.println("1当前线程是中断状态吗?"+Thread.currentThread().isInterrupted()); 19 try { 20 System.out.println("此处准备睡眠"); 21 Thread.sleep(2000); 22 } catch (InterruptedException e) { 23 System.out.println("interrupted when sleep"); 24 //应该在这里再次加中断,sleep报出异常后会清除中断标志 25 System.out.println("2当前线程是中断状态吗?"+Thread.currentThread().isInterrupted()); 26 Thread.currentThread().interrupt(); 27 } 28 29 30 Thread.yield(); 31 } 32 } 33 }; 34 t1.start(); 35 Thread.sleep(2000); 36 t1.interrupt(); 37 } 38 }
while里面加了一个if去判断线程的中断标志位,如果有中断标志的话,就可以合理退出。
值的注意的是,当调用sleep()时,可能被interrupt()方法打断,这这时就会抛出InterruptedException,不仅仅是会抛出异常,而且还会清除标志位,所以在catch语句中会再次添加中断标志。
以上是关于线程的终止stop与线程的中断interrupted的主要内容,如果未能解决你的问题,请参考以下文章