线程的终止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语句中会再次添加中断标志。

时间: 2024-08-10 21:21:34

线程的终止stop与线程的中断interrupted的相关文章

挂起起线程与终止线程的区别

Program1 p1 = new Program1(); Thread th = new Thread(new ThreadStart(p1.ThreadRunMethord));//创建一个新的子线程 if (th.ThreadState != ThreadState.Running)//判断子线程未开始时运行 { th.Start();//启动子线程 } Thread.Sleep(1000);//主线程休眠1秒钟 Console.WriteLine("子线程被挂起而暂停"); i

java 线程的终止与线程中断

关于线程终止: 1.一般来讲线程在执行完毕后就会进入死亡状态,那该线程自然就终止了. 2.一些服务端的程序,可能在业务上需要,常驻系统.它本身是一个无穷的循环,用于提供服务.那对于这种线程我们该如何结束它呢. 一.线程的终止 在Thread类中JDK给我们提供了一个终止线程的方法stop(); 该方法一经调用就会立即终止该线程,并立即释放对象锁.如果当一个线程执行一半业务而调用了该方法,可能就会产生数据不一致问题. 数据一致性:同一时间点,你在节点A中获取到key1的值与在节点B中获取到key1

并发基础(九) java线程的终止与中断

1.简单了解一下:为何不赞成使用 Thread.stop.Thread.suspend 和 Thread.resume? ??suspend .resume.stop方法分别完成了线程的暂停.恢复.终止的工作.不建议使用原因:是因为这三个方法带来的副作用,如suspend( )方法,调用后,线程就会一直占用资源睡眠,直到调用resume( )恢复后,才可以运行.这样很容易引发死锁.同样,stop( )方法在终结一个线程时不会保证线程的资源正常释放,因此会导致程序可能工作在不确定的状态下. ??线

终止阻塞的线程

线程状态 我们知道,一个线程可以处于以下四种状态之一: 1. 新建(New):当线程被创建时,它只会短暂地处于这种状态.此时它已经分配了必须的系统资源,并执行了初始化.此刻线程已经有资格获取CPU时间了,之后调度器将把这个线程转变为可运行状态或阻塞状态. 2. 就绪(Runnable):在这种状态下,只要调度器将CPU时间片分给线程,线程就可以运行.也就是说,在任意时刻,线程可以运行也可以不运行. 3. 阻塞(Blocked):线程能够运行,但有某个或多个条件阻止它运行.当线程处于阻塞状态时,调

java 多线程5: java 终止线程及中断机制 (stop()、interrupt() 、interrupted()、isInterrupted())

JAVA中有3种方式可以终止正在运行的线程 ①线程正常退出,即run()方法执行完毕了 ②使用Thread类中的stop()方法强行终止线程.但stop()方法已经过期了,不推荐使用 ③使用中断机制interrupt() 1.stop()方法 stop()在java多线程中已经废弃 1.stop()方法会导致释放锁的不良后果,数据不完整 比如一个上锁了得方法: threadA线程拥有了监视器,这些监视器负责保护某些临界资源,比如说银行的转账的金额.当正在转账过程中,main线程调用 thread

【转】线程、Thread类和线程终止

一.线程Thread启动 0. Thread类实现了java.lang.Runnable接口,即实现了run方法.虽然在Sun JDK中,start()调用了start0()方法,start0()方法又是native的,但实际上新的线程就是调用了Thread的run()方法,当然这native的实现中一定有线程的fork操作,使两个线程并列执行. 1. Thread类有8个重载的构造方法.在Sun JDK的源码中,这8个构造方法都是调用了一个私有的init()方法来初始化对象的各个属性.这其中会

Java 线程的终止-interrupt

Java线程的终止--interrupt 取消/关闭的场景 我们知道,通过线程的start方法启动一个线程后,线程开始执行run方法,run方法运行结束后线程退出,那为什么还需要结束一个线程呢?有多种情况,比如说: 很多线程的运行模式是死循环,比如在生产者/消费者模式中,消费者主体就是一个死循环,它不停的从队列中接受任务,执行任务,在停止程序时,我们需要一种"优雅"的方法以关闭该线程. 在一些图形用户界面程序中,线程是用户启动的,完成一些任务,比如从远程服务器上下载一个文件,在下载过程

线程的终止

1.Thread的终止 首先,不建议使用Thread类的stop方法,因为会强制释放线程使用的资源,例如锁.文件等,会出现令人意想不到的问题.Java中Thread类提供了interupt方法来设置线程的中断标志位使线程停止,但是interrupt方法并不是万能的,只能在有限的情况下中断线程: 线程处于等待.条件等待时.例如在线程中调用了lock.wait().Thread.sleep()等方法 nio中会能够检测中断标志位的方法 在线程中不断检测了中断标志位.例如在while循环中调用isIn

POSIX 线程编程(二)线程建立与终止

创建与终止线程 线程的管理常用的API有:pthread_create(thread,attr,start_routine,arg) pthread_exit(status) pthread_cancel(thread) pthread_attr_init(attr) pthread_attr_destroy(attr) 创建线程: 一个main程序包含一个默认的主线程,这个主线程在程序开始运行的时候由系统创建.除此之外的所有其他线程必须由程序员显式的创建. pthread_create 创建一