停止线程和暂停线程

停止一个线程意味着在线程处理完任务之前停止正在做的操作,也就是放弃当前的操作,虽然看起来非常简单,但是要做好防范措施。

停止线程的方法

1. 方法1:使用Thread.stop(),但不推荐

2. 方法2:使用Thread.interrupt()

2.1 使用实例:

创建文件MyThread.java:

public class MyThread extends Thread{@Overridepublic void run() {super.run();for (int i = 0;i < 50000 ; i++){System.out.println("i="+i);}}
}

创建测试类RunTest.java:


public class RunTest {public static void main(String[] args) throws InterruptedException {MyThread thread = new MyThread();thread.start();Thread.sleep(2000);thread.interrupt();System.out.println("ZZZZZZZZZ");}
}

预期结果:输出50000行+ZZZZZ,实际输出50001行+zzzz

这说明了什么?调用interrupt()方法并没有真正的把线程停止。

2.2 判断线程是否处于停止状态

2.2.1 public static boolean interrupted():测试currentThread()是否已经中断,执行后具有清除状态标志值为false的功能,如:第一次调用时,当前线程未中断,清除该标志在第二次调用检验中断状态之前,第二次的调用结果就为了true。

2.2.2 public boolean this.isInterrupted():测试this关键字所在类的对象是否已经中断,不清楚状态标志。

3 .判断线程是否处于停止状态即可判断后面的代码是否可运行,如果线程处于停止状态,则后面的代码不再运行。

3.1 能停止的线程------>异常法,如果结果不明显,可配合断点一起使用便于观察结果

修改MyThread.java如下:

public class MyThread extends Thread{@Overridepublic void run() {super.run();for (int i = 0;i < 50000 ; i++){if(this.isInterrupted()){System.out.println("我已经是停止状态了,我要退出了");break;}System.out.println("i="+i);}}
}

修改RunTest.java如下:

public class RunTest {public static void main(String[] args) {try {MyThread thread = new MyThread();thread.start();Thread.sleep(5000);thread.interrupt();}catch (InterruptedException e){System.out.println("main catch");e.printStackTrace();}System.out.println("end!");}
}

实际的运行结果:

i=0
i=1
end!
我已经是停止状态了,我要退出了
3.2 在3.1中的例子虽然停止了线程,但如果for语句下面还有语句,那么程序依然会继续运行,如图:

类MyThread修改如下:

public class MyThread extends Thread{@Overridepublic void run() {super.run();for (int i = 0;i < 50000 ; i++){if(this.isInterrupted()){System.out.println("我已经是停止状态了,我要退出了");break;}System.out.println("i="+i);}System.out.println("我被输出了,是for下的语句,线程结束后我还能执行嘿!");}
}

实际运行结果如下,说明并没有阻止for后的语句再继续执行

i=0
i=1
i=2
end!
我已经是停止状态了,我要退出了
我被输出了,是for下的语句,线程结束后我还能执行嘿!
3.2.1 解决办法,即使用interrupt()正确停止线程的方法

修改MyThread类如下:

public class MyThread extends Thread{@Overridepublic void run() {super.run();try {for (int i = 0;i < 50000 ; i++){if(this.isInterrupted()){System.out.println("我已经是停止状态了,我要退出了");throw  new InterruptedException();}System.out.println("i="+i);}System.out.println("我被输出了,是for下的语句!");}catch (InterruptedException e){System.out.println("进入了MyThread类的run方法中的catch了");e.printStackTrace();}}
}

实际的运行结果部分如下:

i=14006
i=14007
i=14008
i=14009
我已经是停止状态了,我要退出了
end!
进入了MyThread类的run方法中的catch了
java.lang.InterruptedExceptionat MyThread.run(MyThread.java:10)

4.使用“return;”语句和interrupt()方法结合使用停止线程的缺点和解决方案

4.1 修改MyThread类如下:
public class MyThread extends Thread{@Overridepublic void run() {super.run();while(true){if(this.isInterrupted()){System.out.println("停止了哦!");return;}System.out.println("timer:"+System.currentTimeMillis());}}
}
4.2 修改RunTest类如下:
public class RunTest {public static void main(String[] args) throws InterruptedException {MyThread thread = new MyThread();thread.start();Thread.sleep(2000);thread.interrupt();}
}

最后的实际运行结果为,证明停止了之后,没有再继续往下执行

timer:1592300686447
timer:1592300686447
timer:1592300686447
timer:1592300686447
停止了哦!
4.3 使用return的缺点是:不能像抛异常法那样对异常的信息进行统一的处理,解决办法:只能在每个return前都要搭配一个写入日志的操作,所以这会使得代码冗余,所以还是建议使用抛异常的方法来停止线程。

5. 暂停线程

在Java多线程中,可以使用suspend()来暂停线程,resume()来恢复线程的执行。

简单使用的示例:

public class MyThread extends Thread{private long i = 0;public  long getI(){return  i;}public void  setI(long i){this.i = i;}@Overridepublic void run() {super.run();while(true){i++;}}
}

我的RunTest类如下:

public class RunTest {public static void main(String[] args) {try {MyThread thread = new MyThread();thread.start();Thread.sleep(5000);//A段thread.suspend();//此方法已过期,但是研究过期方法为什么被丢弃也是件有趣的事情System.out.println("A="+System.currentTimeMillis()+",i="+thread.getI());Thread.sleep(5000);System.out.println("A="+System.currentTimeMillis()+",i="+thread.getI());//B段thread.resume();Thread.sleep(5000);//C段thread.suspend();System.out.println("B="+System.currentTimeMillis()+",i="+thread.getI());Thread.sleep(5000);System.out.println("B="+System.currentTimeMillis()+",i="+thread.getI());}catch (InterruptedException e){e.printStackTrace();}}
}

最后的运行结果为:

A=1592302312763,i=2823139737
A=1592302317763,i=2823139737
B=1592302322763,i=5736528459 ----》此时线程已被暂停,不再执行run方法的i++
B=1592302327763,i=5736528459 ----->已被暂停的线程,未被恢复,所以i值不变的

5.1 suspend()方法与resume()方法的缺点——————独占资源

如果suspend()方法与resume()方法使用不当,极易造成公共同步对象被占,其他线程无法访问公共对象的结果。

5.1.1 创建模拟公共对象类:
public class SynchronizedObject {synchronized public void printString(){System.out.println("begin");if(Thread.currentThread().getName().equals("a")){System.out.println("a线程永远被暂停了");Thread.currentThread().suspend();}System.out.println("end!");}
}
5.1.2 创建RunTest类:
public class RunTest {public static void main(String[] args) {try {final SynchronizedObject obj = new SynchronizedObject();Thread thread1 = new Thread(){@Overridepublic void run() {obj.printString();}};thread1.setName("a");thread1.start();Thread.sleep(1000);Thread thread2 = new Thread(){@Overridepublic void run() {System.out.println("Thread2启动了,但却进入不了printString,无法打印出b的begin");obj.printString();}};thread2.setName("b");thread2.start();}catch (InterruptedException e){e.printStackTrace();}}
}

实际运行结果,A线程独占并锁死了公共资源printString()方法

begin
a线程永远被暂停了
Thread2启动了,但却进入不了printString,无法打印出b的begin

5.2 另一种独占资源锁死的情况

5.2.1 创建MyThread类:
public class MyThread extends Thread{private long i = 0;@Overridepublic void run() {super.run();while(true){i++;}}
}
5.2.2 创建RunTest类:
public class RunTest {public static void main(String[] args) {try {MyThread thread = new MyThread();thread.start();Thread.sleep(1000);thread.suspend();System.out.println("mainEnd!");}catch (InterruptedException e){e.printStackTrace();}}
}

运行结果如下:输出mainEnd,但是可以看到进程未被销毁,在控制台看到是呈红色按钮。

但是如果将MyThread.java更改成如下:

public class MyThread extends Thread{private long i = 0;@Overridepublic void run() {super.run();while(true){i++;System.out.println(i);}}
}

运行结果如下:未输出mainEnd

144067
144068
144069
144070
144071
144072
144073
144074

产生这种情况的原因是:当程序运行到System.out.prtintln(i)内部时,同步锁是不释放的,println()的源代码如下:

 public  void  println(long x){synchronized (this){print(x);newLine();}}

以上便是多线程的暂停和彻底停止的内容,关于suspend()和resume()一起使用还可能造成数据的不完整的缺点这里就不再述说,现在JDK版本已经将这两个方法作废了,想要对线程进行暂停与恢复的处理,可使用wait(),notify()或notifyAll()方法。

【探索】停止线程和暂停线程相关推荐

  1. 十分钟搞定Java多线程-如何使用sleep()方法和TimeUnit暂停线程

    为什么要使用sleep暂停线程 有多种方法可以暂停或停止当前正在运行的线程,但是使用Thread.sleep()方法将线程置于睡眠状态才是暂停线程的正确方法.有些人会说,为什么不用wait和notif ...

  2. android线程作用,Android线程介绍

    进程与线程 进程:是操作系统的基础:是一次程序的执行:是一个程序及数据在处理机上顺序执行时所发生的活动:是程序在一个数据集合运动的过程:它是系统进行资源分配的一个独立单位. 线程:线程可以理解成是在进 ...

  3. android线程安全ppt,线程进程安全.ppt

    线程进程安全.ppt 第三章 线程 进程安全 进程和线程是两个范围不同的概念 进程是程序在计算机上的一次执行活动 运行一个程序 相当于启动了一个进程 进程是操作系统进行资源分配的单位 通俗地讲 是一个 ...

  4. 【Java 语言】Java 多线程 一 ( 线程基础 : 线程启动 | 线程停止 | 线程暂停 | 线程优先级 | 守护线程)

    一. 线程启动 线程启动 : -- 1. 继承 Thread 运行线程 : 重写 Thread 类的 run 方法, 然后执行该线程; -- 2. 实现 Runnable 接口, 并运行线程; -- ...

  5. 停止线程 暂停线程

    停止线程 停止一个线程意味着在线程处理完任务之前停止正在进行的操作,即放弃当前的操作. Java中有以下3中方法可以终止正在运行的线程: 使用退出标志,使线程正常退出(当run方法完成后线程终止) 使 ...

  6. 让线程实现暂停,重新启动,停止

    public class BaseThread extends Thread{private final static Logger logger = Logger.getLogger(BaseThr ...

  7. C++ :线程的暂停、恢复和停止

    转载:C++11: 线程的暂停和继续和停止_hai7song的专栏-CSDN博客_c++ 线程暂停 重点: 通过设置一个类,类里面加入线程,然后采用标志位来控线程的暂停.恢复和停止. 有点意思! #i ...

  8. python threading 停止和暂停线程

    python的threading包,暂停线程.恢复线程,和停止线程的方法 import threading import timeclass Job(threading.Thread):def __i ...

  9. Java终止或暂停线程

    前言 停止线程 使用stop()方法 代码实例 stop()存在的问题 使用interrupt()中断线程 实例代码 interrupted()和isInterrupted() 暂停线程 实例代码 s ...

最新文章

  1. 哈勃望远镜进一步确认宇宙在加速膨胀
  2. 线程队列 线程池 协程
  3. 关于WCF中间层服务器端DTO属性更新如何同步回仓储实体的处理方式
  4. select 移动端 第一个无法选中_总结在移动端碰到的坑
  5. MotionVFX - mForm for Mac - 150种MG动态图形元素fcpx插件
  6. PHP获取URL完整路径及物理路径
  7. 详解 Qt 串口通信程序全程图文 (4)
  8. rust怎么关阳光指令_我家也有庭院多好,伸缩阳光房装上,能休闲能当车库,还不算违建...
  9. QTP的那些事 -– Visual Relation Identifier Feature: How to use in the real world
  10. 洛谷P3378 【模板】堆
  11. 软件测试个人绩效模板,测试工程师kpi模板.doc
  12. wps折线图如何画多条折线_如何用wps制作折线图
  13. 剪辑师的基本素养--了解四种特写类型
  14. 8421码转16进制的c语言,16进制数转换成8421BCD编码函数
  15. 纯css绘制简易对话气泡
  16. 敏捷开发Scrum学习
  17. [C语言错误]expected declaration or statement at end of input)
  18. win7笔记本网络连接图标一直转圈但可上网
  19. 如何修改项目中Git远程仓库地址?
  20. BigBrother的大数据之旅Day 15 sqoop

热门文章

  1. id3 c4.5 cart之间区别
  2. 一个页面调用另一个页面的方法
  3. 测试开发工作者的日记:2020.6.3
  4. 十二款世界顶级杀毒软件下载,有序列号全可免费升级
  5. vue 的axios 文件上传
  6. php网站源码 闪拍拍卖转拍 微拍堂自动挂售竞拍程序 H5拍卖商城系统+app
  7. c++ 入门(自学过程)
  8. 1510 出纳员问题
  9. 纯前端实现—猜数字游戏
  10. Linux下安装jdk