1. 首页
  2. 网络编程教程

002-二、网络编程之线程停止详解

引言

多线程中有三种方式可以停止线程。
设置标记位,可以是线程正常退出。
使用stop方法强制使线程退出,但是该方法不太安全所以已经被废弃了。
使用Thread类中的一个interrupt() 可以中断线程。
设置标记位停止线程

先看代码


class MyRunnable implements Runnable { /** * 定义一个关闭线程的标记,首先为false */ private boolean flag = true; @Override public void run() { int i = 1; try { while (flag) {//这里是无限循环 Thread.sleep(1000);//为了演示效果所以加上了休眠 System.out.println("第" + (i) + "次执行,线程名称" + Thread.currentThread().getName()); i++; } } catch (InterruptedException e) { e.printStackTrace(); } } /** * 将标记设置为false */ public void setFlag() { this.flag = false; } } MyRunnable myRunnable = new MyRunnable(); Thread thread = new Thread(myRunnable); thread.setName("A..."); thread.start();//启动线程 Thread.sleep(3000);//设置2秒之后在停止线程 myRunnable.setFlag();//设置停止线程的状态 结果: 第1次执行,线程名称A... 第2次执行,线程名称A... 第3次执行,线程名称A...

使用stop方法强制使线程退出

使用stop方法强制使线程退出,但是该方法不太安全所以已经被废弃了。
为什么说不安全呢?因为stop会解除由线程获取的所有锁定,当在一个线程对象上调用stop()方法时,这个线程对象所运行的线程就会立即停止,假如一个线程正在执行:synchronized void { x = 3; y = 4;} 由于方法是同步的,多个线程访问时总能保证x,y被同时赋值,而如果一个线程正在执行到x = 3;时,被调用了 stop()方法,即使在同步块中,它也会马上stop了,这样就产生了不完整的残废数据。

这个演示也不是每次都能测试出来的。所以就演示一下怎么使用stop吧!
MyRunnable类代码不变,修改一下执行代码即可。


MyRunnable myRunnable = new MyRunnable(); Thread thread = new Thread(myRunnable); thread.setName("A..."); thread.start();//启动线程 Thread.sleep(3000);//设置2秒之后在停止线程 thread.stop();//设置停止线程的状态 结果: 第1次执行,线程名称A... 第2次执行,线程名称A...

以上大家可以看出来了吧,其实就是在循环的条件上做手脚就好了,因为每次循环都会根据这个while条件来判断的,所以在开启线程之后休眠3秒之后在将while条件设置为false就可以跳出循环了,随之也会自动停止线程了。

使用Thread类中的一个interrupt()

interrupt() 方法只是改变中断状态而已,它不会中断一个正在运行的线程。这一方法实际完成的是,给受阻塞的线程发出一个中断信号,这样受阻线程就得以退出阻塞的状态。

然而interrupte()方法并不会立即执行中断操作;具体而言,这个方法只会给线程设置一个为true的中断标志(中断标志只是一个布尔类型的变量),而设置之后,则根据线程当前的状态进行不同的后续操作。

如果,线程的当前状态处于非阻塞状态,那么仅仅是线程的中断标志被修改为true而已;如果线程的当前状态处于阻塞状态,那么在将中断标志设置为true后,还会有如下三种情况之一的操作:

如果是wait、sleep以及jion三个方法引起的阻塞,那么会将线程的中断标志重新设置为false,并抛出一个InterruptedException

如果是java.nio.channels.InterruptibleChannel进行的io操作引起的阻塞,则会对线程抛出一个ClosedByInterruptedException;(待验证)

如果是轮询(java.nio.channels.Selectors)引起的线程阻塞,则立即返回,不会抛出异常。(待验证)

如果在中断时,线程正处于非阻塞状态,则将中断标志修改为true,而在此基础上,一旦进入阻塞状态,则按照阻塞状态的情况来进行处理;例如,一个线程在运行状态中,其中断标志被设置为true之后,一旦线程调用了wait、jion、sleep方法中的一种,立马抛出一个InterruptedException,且中断标志被程序会自动清除,重新设置为false

通过上面的分析,我们可以总结,调用线程类的interrupted方法,其本质只是设置该线程的中断标志,将中断标志设置为true,并根据线程状态决定是否抛出异常。因此,通过interrupted方法真正实现线程的中断原理是:开发人员根据中断标志的具体值,来决定如何退出线程。

下面将演示。


class MyRunnable implements Runnable { @Override public void run() { int i = 1; try { //这里是无限循环 while (true) { /** * 这里阻塞之后,线程被调用了interrupte()方法, * 清除中断标志,就会抛出一个异常 * java.lang.InterruptedException */ Thread.sleep(1000); /** * 运行状态,线程被调用了interrupte()方法,中断标志被设置为true * 非阻塞状态中进行中断线程操作,因为上面有Thread.sleep(1000) * 所以已经睡眠阻塞了那么这块代码是不会执行的。 */ boolean bool = Thread.currentThread().isInterrupted(); if (bool) { System.out.println("非阻塞情况下执行该操作。。。线程状态" + bool); break; } System.out.println("第" + (i) + "次执行"); i++; } } catch (Exception e) { System.out.println("退出了"); /** * 这里退出阻塞状态,且中断标志被系统会自动清除, * 并且重新设置为false,所以此处bool为false */ boolean bool = Thread.currentThread().isInterrupted(); System.out.println(bool); return; //退出run方法,中断进程 } } //代码中的注释还是比较详细的。 //执行代码 MyRunnable myRunnable = new MyRunnable(); Thread thread = new Thread(myRunnable); thread.start(); Thread.sleep(3000); thread.interrupt();//中断线程,将中断标识设置成true 结果: 第1次执行 第2次执行 退出了

写完了如果写得有什么问题,希望读者能够给小编留言,也可以点击[此处扫下面二维码关注微信公众号](https://www.ycbbs.vip/?p=28 "此处扫下面二维码关注微信公众号")

看完两件小事

如果你觉得这篇文章对你挺有启发,我想请你帮我两个小忙:

  1. 关注我们的 GitHub 博客,让我们成为长期关系
  2. 把这篇文章分享给你的朋友 / 交流群,让更多的人看到,一起进步,一起成长!
  3. 关注公众号 「方志朋」,公众号后台回复「666」 免费领取我精心整理的进阶资源教程
  4. JS中文网,Javascriptc中文网是中国领先的新一代开发者社区和专业的技术媒体,一个帮助开发者成长的社区,是给开发者用的 Hacker News,技术文章由为你筛选出最优质的干货,其中包括:Android、iOS、前端、后端等方面的内容。目前已经覆盖和服务了超过 300 万开发者,你每天都可以在这里找到技术世界的头条内容。

    本文著作权归作者所有,如若转载,请注明出处

    转载请注明:文章转载自「 Java极客技术学习 」https://www.javajike.com

    标题:002-二、网络编程之线程停止详解

    链接:https://www.javajike.com/article/1225.html

« 003-三、网络编程之线程优先级和守护详解
001-一、网络编程之多线程Runnable»

相关推荐

QR code