大奖18dj18vip-大奖18dj18娱乐官网

【腾讯云】618云聚惠,百款云产品限量抢购,1核2G云服务器首年95元 http://cloud.tencent.com/act/cps/redirect?redirect=1059&cps_key=9f7b3aa0b9ee11c8648ef8bf9d4f15a9&from=console

大奖18dj18vip

大奖18dj18vip 门户 教程 电脑网络 查看内容

撸一撸如何优雅地中止线程?

2020-3-27 14:04| 发布者: 虚拟主机评测| 查看: 20| 评论: 0

摘要: 本文来学习如何学习优雅地中止线程?通过 Java 线程的生老病死的学习,我相信大家对线程的运行以及线程的状态有一定了解了,那么我们现在来学习中止线程:错误的线程中止 - stop首先来讲解一个错误的方式来中止线程 ...

 

本文来学习如何学习优雅地中止线程?通过 Java 线程的生老病死的学习,我相信大家对线程的运行以及线程的状态有一定了解了,那么我们现在来学习中止线程:

错误的线程中止 - stop

首先来讲解一个错误的方式来中止线程 — stop:中止线程,并且清除监控器锁的信息,但是可能导致线程安全问题,JDK 不建议使用,类似的方法还有 destory,由于 JDK 从未实现该方法,在这里就不介绍了。

接下来通过一段程序来讲解为什么 stop 会导致线程安全问题?

首先定义一个线程类 StopThread:

  1. CIMAl; border: none; line-height: 21px; font-family: Arial; background: url(" http:="" images.51cto.com="" images="" art1105="" 0.gif")="" -498px="" -70px="" repeat-y="" scroll="" transparent;="" color:="" inherit;="" padding:="" 0px="" 3px="" 10px="" !important;="" margin:="" list-style-position:="" outside="" !important;"="">public class StopThread extends Thread { 
  2.     private int i = 0; 
  3.     private int j = 0; 
  4.  
  5.     @Override 
  6.     public void run() { 
  7.         synchronized (this) { 
  8.             // 增加同步锁,确保线程安全 
  9.             ++i; 
  10.             try { 
  11.                 // 休眠10秒,模拟耗时操作 
  12.                 Thread.sleep(10000); 
  13.             } catch (InterruptedException e) { 
  14.                 e.printStackTrace(); 
  15.             } 
  16.             ++j; 
  17.         } 
  18.     } 
  19.  
  20.     /** 
  21.      * 打印 i 和 j 
  22.      */ 
  23.     public void print() { 
  24.         System.out.println("i=" + i + " j=" + j); 
  25.     } 

这个线程做的事情就是在同步代码块中对 i 和 j 这两个变量进行自增操作,但是在这个执行过程中会进行 10 秒的睡眠,如果在这个过程中,如果用 stop 方法将线程中止的话,会导致 i 和 j 数据不正确,也可以说程序设计上的线程安全问题,因为主线程影响到了创建的 StopThread 线程的数据不正确性,理想的正确输出结果应该是要么全部添加成功,要么都失败,因为我们添加锁的目的就是保证操作原子性或者说想让这两个变量在操作的时候不受其他线程干扰。

下面编写 StopThreadDemo 类,来使用 stop 方法做个错误示范:

  1. public class StopThreadDemo { 
  2.     public static void main(String[] args) throws InterruptedException { 
  3.         StopThread thread = new StopThread(); 
  4.         thread.start(); 
  5.         // 休眠 1 秒,确保 i 变量自增成功 
  6.         Thread.sleep(1000); 
  7.         // 暂停线程 
  8.         thread.stop(); // 错误的终止 
  9.         while (thread.isAlive()) { 
  10.             // 确保线程已经终止 
  11.         } // 输出结果 
  12.         thread.print(); 
  13.     } 

在 StopThreadDemo 类中,创建并启动了 StopThread 线程,这个线程就是下执行变量i 和 j 的自增操作,但是这个自增操作是用同步关键字包裹的同步代码块,这样做是为了让两个变量的自增操作实现原子性,不会受到其他线程的干扰,确保线程的安全。

但是在线程休眠的 10 秒内,通过 stop 方法把线程中止掉,会发现输出结果为 i=1 j=0,也就是代码的前半段 i 自增实现,但是后半段 j 的自增失败,会使线程中的数据出现不一致性,从而同步代码块的保证的原子性的目标没有达成,破坏了线程安全。

正确的线程中止 - interrupt

在介绍了错误的中止方式后,让我们来学习正确的线程中止 - interrupt :

如果目标线程在调用 Object class 的 wait() 、wait(long) 或 wait(long,int) 方法、join()、join(long,int) 或 sleep(long,int) 方法时阻塞,那么 interrupt 会生效,该线程的中断状态将被清除,抛出 InterruptedException 异常。

如果目标线程是被 IO 或者 NIO 中的 Channel 所阻塞,同样 IO 操作会被中断返回特殊异常值,达到中止线程的目的。

如果以上条件都不满足,则会设置此线程的中断状态。

接下来将 StopThreadDemo 中的 stop 改为 interrupt 来看下运行结果是什么:

  1. java.lang.InterruptedException: sleep interrupted 
  2.   at java.lang.Thread.sleep(Native Method) 
  3.   at com.wupx.thread.StopThread.run(StopThread.java:18) 
  4. i=1 j=1 

可以发现两个变量的自增可以正常执行,保证了执行的数据一致性,interrupt 不会强制中止,将线程直接中断,而是抛出异常通知我们,开发者就可以控制收到异常后的执行逻辑,让整个程序处于线程安全的状态,这是目前 JDK 版本中推荐的 interrupt 方法。

除了 interrupt 的正确方法外,还可以通过标志位的形式来中止线程:

正确的线程中止 - 标志位如果代码程序逻辑中是循环执行的业务,可以在程序的执行中线程代码中增加一个标志位,比如下面代码中在 while 循环中去执行这个程序,通过 flag 去控制程序是否继续执行,如果在外部线程将 flag 修改为 false,那么创建的子线程代码中会收到这个数据的变化,通过这个变量的形式,通知到另一个线程,从而达到控制线程中止的效果。

  1. java.lang.InterruptedException: sleep interrupted 
  2.   at java.lang.Thread.sleep(Native Method) 
  3.   at com.wupx.thread.StopThread.run(StopThread.java:18) 
  4. i=1 j=1 

通过运行代码,得到的结果如下:

  1. 运行中 
  2. 运行中 
  3. 运行中 
  4. 程序运行结束 

这种方式受限于线程中所执行的业务逻辑,如果程序中是有可以用来做标志位的条件的话可以用这种方式来做,也是一种正确的线程中止方式。

总结

本文主要学习了线程中止的三种方式:stop、interrupt 以及标志位,大家学会了吗,欢迎留言讨论。

大奖18dj18vip社区温馨提示:
大奖18dj18vip(www.dastanona.com)十分重视网络版权及其他知识产权的保护,针对网络侵权采取如下版权政策:
1、大奖18dj18vip有理由相信网友侵犯任何人的版权或作品,(图文,文字,下载,视频,非法传播),大奖18dj18vip有权不事先通知即删除涉嫌侵权的作品和内容
2、大奖18dj18vip将采取必要的网络技术手段,确认为侵权作品或内容的用户有权进行警告、屏蔽、删除的行为,尽可能的防止侵权行为的发生
3、大奖18dj18vip影视资源均收集自互联网,没有提供影片资源存储,也未参与录制上传,若大奖18dj18vip收录的资源涉及您的版权或知识产权或其他利益,我们会立即删除
4、大奖18dj18vip,删帖,投诉,举报,侵权,若大奖18dj18vip侵犯您的权益,附上身份及权利证明,请直接发送邮件到 kefu-sosoba@qq.com 我们将在一个工作日内删除

鲜花

握手

雷人

路过

鸡蛋

最新评论

资讯分类

推荐图文

文章排行

Powered by www.dastanona.com Copyright © 2013-2020 大奖18dj18vip社区 小黑屋|手机版|地图|关于我们|腾讯云代金券|帮助中心|公共DNS|大奖18dj18vip
广告服务/项目合作: kefu-sosoba@qq.com  侵权举报邮箱: kefu-sosoba@qq.com  大奖18dj18vip建站时间:创建于2013年07月23日
免责声明:大奖18dj18vip所有的内容均来自互联网以及第三方作者自由发布,版权归原作者版权所有,大奖18dj18vip不承担任何的法律责任,若有侵权请来信告知,我们立即删除!

GMT+8, 2020-5-27 10:41 , Processed in 1.132767 second(s), 8 queries , MemCache On.

返回顶部