一. 停止线程会带来什么?
对于单线程中, 停止单线程就是直接使用关键字 return 或者 break, 但是在停止多线程时是让线程在完成任务前去开启另外一条线程, 必须放弃当前任务, 而这个过程是不可预测, 所以必须去做好防备.
二. 认识停止线程的几个方法
2.1 三个被弃用的方法
stop(),suspend(),resume().
stop() 方法被弃用的原因: 无论线程执行到了什么位置, 一旦被 stop 就会被马上强制中断, 并且释放线程所有持有锁对象, 根本就没有安全性.
suspend() 和 resume() 这一对烂兄烂弟, 因为只有其他线程调用 resume 这个方法时他才会释放 suspend 这个方法的锁, 这样就极易造成死锁.
2.2 三个名字差不多的方法
interrupt() 中断线程, interrupted() 判断当前线程是否停止, isInterrupted() 判断线程是否停止.
首先来介绍一下其中两个名字最相近的: interrupted(),isInterrupted() 方法, 这两个方法是用来测试线程是否被中断的.
来看一下原码:
- isInterrupted():
- public boolean isInterrupted() {
- return isInterrupted(false);
- }
- interrupted():
- public static boolean interrupted() {
- return currentThread().isInterrupted(true);
- }
可以明显看出 interrupted() 方法是静态的, 而 isInterrupted() 是非静态的, 但都是返回线程是否被中断.
下面我们来做一个测试, 代码如下:
- public class Is_Interrupt extends Thread{
- @Override
- public void run(){
- for(int i=0;i<1000;i++){
- System.out.println("当前 i 的值为:"+i);
- }
- }
- public static void main(String[] args) {
- Is_Interrupt is_interrupt=new Is_Interrupt();
- is_interrupt.start();
- is_interrupt.interrupt();// 中断线程
- System.out.println("线程是否已经暂停?"+is_interrupt.interrupted());
- }
- }
输出结果为:
发现线程没有停止.
但是这里面还有一个线程就是 main 线程, 而 interrupted() 返回的就是当前线程的中断状态, 那么执行这个方法的就是 main 线程, 而 main 线程此时当然没有中断.
我们将 interrupted() 方法改为 isInterrupted() 试试效果, 代码如下:
- public class Is_Interrupt extends Thread{
- @Override
- public void run(){
- for(int i=0;i<1000;i++){
- System.out.println("当前 i 的值为:"+i);
- }
- }
- public static void main(String[] args) {
- Is_Interrupt is_interrupt=new Is_Interrupt();
- is_interrupt.start();
- is_interrupt.interrupt();// 中断线程
- System.out.println("线程是否已经暂停?"+is_interrupt.isInterrupted());
- }
- }
结果如下:
说明线程是已经停止了的, 只不过我们使用错了一个方法而已判断成了 main 线程的状态.
总结: isInterrupted 方法是返回调用对象的中断状态, 而静态方法 interrupted 是返回当前线程的中断状态.
既然了解了这个误区以后我们再来看看下面的代码:
- public class InterruptText extends Thread{
- public static void main(String[] args) {
- System.out.println("main 线程启动!");
- System.out.println( Thread.interrupted());// 判断当前线程是否中断
- System.out.println(currentThread().isInterrupted());// 通过 currentThread().isInterrupted() 同样也可以达到相同的目的, 在单线程中
- }
- }
输出:
这个是没有问题的.
那么我们多次调用这个 interrupted 方法呢?
- public class InterruptText extends Thread{
- public static void main(String[] args) {
- System.out.println("main 线程启动!");
- currentThread().interrupt();// 中断 main 线程
- System.out.println( Thread.interrupted());// 判断当前 main 线程是否中断
- System.out.println( Thread.interrupted());// 再一次判断当 main 前线程是否中断
- }
- }
结果: 按照常理应该两次返回 ture, 但是为什么变成了第二次变成了 false 了呢?
其实 interrupted 就是在清除状态, 你两次调用当然会将 true 变成 flase 但是他还是中断状态, 但是 isInterrupted 是不清除的.
interrupt() 方法: 中断线程
三. 停止线程
3.1 通过异常来暂停线程
首先来看一段代码:
- public class InterruptText extends Thread{
- @Override
- public void run(){
- try {
- for (int i = 0; i < 100000; i++) {
- if (currentThread().isInterrupted()) {// 如果线程中断
- throw new InterruptedException();// 抛出异常
- } else {
- System.out.println(i);
- }
- }
- System.out.println("线程没有终止");
- }catch (InterruptedException e){
- e.printStackTrace();
- }
- }
- public static void main(String[] args) throws Exception {
- InterruptText interruptText=new InterruptText();
- interruptText.start();
- Thread.sleep(100);
- interruptText.interrupt();
- }
- }
结果:
异常停止方法的策略就是: 在遇到中断时, 抛出异常, 扑捉异常.
3.2 在睡眠中中断线程
代码如下:
- public class InterruptText2 extends Thread {
- @Override
- public void run(){
- try {
- Thread.sleep(10000);// 线程睡眠
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- public static void main(String[] args) {
- InterruptText2 interruptText2=new InterruptText2();
- interruptText2.start();// 开启线程, 但是线程处于睡眠状态
- interruptText2.interrupt();// 在睡眠状态中断线程
- }
- }
结果为:
3.3 线程让步
方法: yield(), 当前线程放弃所有的资源, 去执行其他的任务. 但是放弃资源的时间不可以预判的.
3.4 守护线程
守护线程的定义: 守护线程是一种特殊的线程, 区别于非守护线程, 当程序中不存在非守护线程时, 守护线程退出, 程序退出.
设置守护线程: setDaemon(), 参数为 ture 则该线程为守护线程.
来源: https://www.cnblogs.com/SAM-CJM/p/9787929.html