Java中线程的停止,暂停,恢复

概念知识

简述

暂停、恢复和停止操作对应在线程Thread的API就是suspend()、resume()和stop()。但是这些API是过期的,也就是不建议使用的。不建议使用的原因主要有:
以suspend()方法为例,在调用后,线程不会释放已经占有的资源(比如锁),而是占有着资源进入睡眠状态,这样容易引发死锁问题。
同样,stop()方法在终结一个线程时不会保证线程的资源正常释放,通常是没有给予线程完成资源释放工作的机会,因此会导致程序可能工作在不确定状态下。正因为suspend()、resume()和stop()方法带来的副作用,这些方法才被标注为不建议使用的过期方法。

停止线程

1.stop 这个不建议,因为过期了. stop相当于linux的kill进程,是非常暴力的,我不知道用户是不是还有请求没处理完的,这样我强制关闭,可能会有不可预测的问题出现

2.interrupt 优雅的中断,建议用这个
先去阻止后续的请求进来,同时等待当前正在执行的进程都处理完了再去停止掉线程

3…通过指令的方式, volatile boolean isStop = false;

volatile是线程可见的.

4…Thread.interrupted();

对设置的中断标识的线程进行复位,就是给interrupted 变成false.

与线程中断有关的方法有三个:

public void Thread.interrupt() //中断线程
public boolean Thread.isInterrupted() //判断是否被中断
public static boolean Thread,interrupted() //判断是否被中断,并清除当前的中断状态

线程通过方法isInterrupted()来进行判断是否被中断,也可以调用静态方法Thread.interrupted()来进行判断当前线程是否被中断,不过Thread.interrupted()会同时将中断标识位改写为false。

isInterrupted()方法是boolean类型的,如果这个线程被中断了就返回true,否则就返回false

如果一个线程处于了阻塞状态(如线程调用了thread.sleep、thread.join、thread.wait等),则在线程在检查中断标示时如果发现中断标示为true,则会在这些阻塞方法调用处抛出InterruptedException异常,并且在抛出异常后会立即将线程的中断标示位清除,即重新设置为false。

不建议自定义一个取消标志位来中止线程的运行。因为run方法里有阻塞调用时会无法很快检测到取消标志,线程必须从阻塞调用返回后,才会检查这个取消标志。这种情况下,使用中断会更好,因为,

一、一般的阻塞方法,如sleep等本身就支持中断的检查,
二、检查中断位的状态和检查取消标志位没什么区别,用中断位的状态还可以避免声明取消标志位,减少资源的消耗。
注意:处于死锁状态的线程无法被中断

案例interrupt 方式中断线程

中断Thread线程

一秒后中断线程
执行main方法查看控制台打印,和后面的时间戳.你会发现1000毫秒(一秒)后线程中断了


import utils.SleepTools;

public class UseThread extends Thread {
    
    
	public UseThread(String name) {
    
    
		super(name);
	}

	@Override
	public void run() {
    
    
		String threadName = Thread.currentThread().getName();
		while (!isInterrupted()) {
    
    //检查当前线程是否被中断(平时开发用这个就行了)

			System.out.print(threadName + " 正在运行    ,");
			System.out.println(threadName + "内部interrrupt标记 = "
					+ isInterrupted() + "当前系统时间戳是" + System.currentTimeMillis());

		}

		//建议在下面的输出语句打断点,更好的查看效果
		System.out.print("线程将要停止了,   ");
		System.out.println(threadName + " interrrupt标记 =" + isInterrupted()+ "  当前系统时间戳是" + System.currentTimeMillis() );//变成true就是中断了
	}

	public static void main(String[] args) {
    
    
		UseThread thread = new UseThread("线程1");
		thread.start();
		SleepTools.second(1);//睡眠一秒
		thread.interrupt();//中断线程,其实设置线程的标识位true

	}
}

中断Runnable线程

一秒后中断线程
执行main方法查看控制台打印,和后面的时间戳.你会发现1000毫秒(一秒)后线程中断了


import utils.SleepTools;

public class UseRunnable implements Runnable {
    
    
	@Override
	public void run() {
    
    
//		boolean interrupted = Thread.currentThread().isInterrupted(); 主要这么写,中断线程无效
//		while (!interrupted) {// 不要这么写,中断线程无效

		while (!Thread.currentThread().isInterrupted()) {
    
    
			System.out.println(Thread.currentThread().getName()
					+ "我是实现Runnable的线程,此时的interrupt标记位是 "
					+ Thread.currentThread().isInterrupted() + "当前系统时间戳是" + System.currentTimeMillis());
		}

		System.out.println(Thread.currentThread().getName() + "interrupt 标记 是" +
				Thread.currentThread().isInterrupted() + "当前系统时间戳是" + System.currentTimeMillis());
	}


	public static void main(String[] args) {
    
    
		UseRunnable useRunnable = new UseRunnable();
		Thread thread = new Thread(useRunnable, "Runnable线程");
		thread.start();

		SleepTools.second(1);//睡眠一秒

//		Thread.currentThread().interrupt(); 这样中断线程是无效的,不要这么写

		thread.interrupt(); //设置中断线程

	}
}


发生异常中断线程

如果想发成异常就中断线程,请在catch代码块儿里面用Thread.currentThread().interrupt();
如果不这样做会发生某些后果,具体后果运行下面代码去查看效果.



import utils.SleepTools;

public class UseRunnable implements Runnable {
    
    
	@Override
	public void run() {
    
    
//		boolean interrupted = Thread.currentThread().isInterrupted(); 主要这么写,中断线程无效
//		while (!interrupted) {// 不要这么写,中断线程无效

		while (!Thread.currentThread().isInterrupted()) {
    
    
			try {
    
    

				System.out.println(Thread.currentThread().getName() + "我是实现Runnable的线程,此时的interrupt标记位是 " + Thread.currentThread().isInterrupted());
				int a = 1 / 0;
			} catch (Exception e) {
    
    
				/*需要在catch里面手动中断一下,如果想知道不这样写的后果,
				可以注释这个代码试试  , 然后仔细观察控制台打印输出语句.,*/
//				Thread.currentThread().interrupt();
				e.printStackTrace();
			}


		}

		System.out.println(Thread.currentThread().getName() + "interrupt 标记 是" +
				Thread.currentThread().isInterrupted());
	}


	public static void main(String[] args) {
    
    
		UseRunnable useRunnable = new UseRunnable();
		Thread thread = new Thread(useRunnable, "Runnable线程");
		thread.start();

		SleepTools.second(1);//睡眠一秒

//		Thread.currentThread().interrupt(); 这样中断线程是无效的,不要这么写

		thread.interrupt(); //设置中断线程

	}
}


猜你喜欢

转载自blog.csdn.net/qq_41489540/article/details/109109945