栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

面试官:如何停止一个正在运行的线程

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

面试官:如何停止一个正在运行的线程

停止一个线程意味着在任务处理完任务之前停掉正在做的操作,也就是放弃当前的操作。停止一个线程可以用Thread.stop() 方法。

使用 stop 方法中止线程
public class ThreadTest{

	 static class Thread1 extends Thread {
	        @Override
	        public void run() {
	            for (int i = 0; i < 500000; i++) {
	                System.out.println("打印的数字"+i);
	            }
	        }
	 }
	public static void main(String[] args) throws InterruptedException {
		Thread1 thread1 = new Thread1();
		thread1.start();
        //保证子线程进入运行状态,避免还没运行就被终止
        Thread.sleep(100);
        //暴力停止子线程
        thread1.stop();
	}

}

输出结果如下:

可以看得出,线程确实被终止了。但最好不要用它。虽然它确实可以停止一个正在运行的线程,但是这个方法是不安全的,而且是已被废弃的方法。


这里面的解释就是:

Stop 方法时被废弃掉的方法,不推荐使用,使用 Stop 方法,会一直向上传播 ThreadDeath 异常,从而使得目标线程解锁所有锁住的监视器,即释放掉所有的对象锁。使得之前被锁住的对象得不到同步的处理,因此可能会造成数据不一致的问题。注释中建议我们取代 Stop 方法,可以增加一个变量。目标线程周期性地检查这个变量。如果变量在某个时间指示线程终止,则目标线程将以有序的方式从 run 方法中返回。当然,如果目标线程长时间进行等待,则可以使用中断的方式来终止线程。

使用退出标志终止线程

通过指定一个条件变量,线程可以控制该变量,内部线程在内部循环检查该变量。

public class ThreadTest extends Thread {

	    public volatile boolean exit = false; 

	    public void run() { 
	        while (!exit); 
	    } 
	public static void main(String[] args) throws InterruptedException {
		ThreadTest thread = new ThreadTest(); 
        thread.start(); 
        Thread.sleep(5000); // 主线程延迟5秒 
        thread.exit = true;  // 终止线程thread 
        thread.join(); 
        System.out.println("线程退出!"); 
	}

}

在上面代码中定义了一个退出标志 exit,当 exit 为 true 时,while 循环退出,exit 的默认值为 false,在定义 exit 时,使用了 Java 关键字 volatile,这个关键字可以是 exit 同步,也就是说在同一时刻只能由一个线程来修改 exit 的值, 可以参考我的另外一篇文章: volatile底层实现原理详解

使用 interrupt 方法终止线程
public class ThreadTest extends Thread {

	   private boolean flag = true;

	    @Override
	    public void run() {
	        while (flag) {
	            synchronized (this) {

	                try {
	                    sleep(10000);
	                } catch (InterruptedException e) {
	                    e.printStackTrace();
	                    this.stopThread();
	                }
	            }
	        }
	    }

	    public void stopThread() {
	        System.out.println("线程已经退出。。。");
	        this.flag = false;
	    }
	public static void main(String[] args) throws InterruptedException {
		    ThreadTest threadTest = new ThreadTest();
		    threadTest.start();
	        System.out.println("线程开始");
	        try {
	            Thread.sleep(5000);
	        } catch (InterruptedException e) {
	            e.printStackTrace();
	        }
	        threadTest.interrupt();
	}

}

interrupt 方法用来设置线程的中断状态,如果目标线程正阻塞于 wait、sleep 等方法时,首先会清除目前线程的中断状态,然后抛出 java.lang.InterruptedException异常

使用 Thread.isInterrupted() 终止线程
public class ThreadTest extends Thread {
	 int count=0;
	   public void run(){
	       System.out.println(getName()+"将要运行...");
	       while(!this.isInterrupted()){
	           System.out.println(getName()+"运行中"+count++);
	           try{
	               Thread.sleep(400);
	           }catch(InterruptedException e){
	               System.out.println(getName()+"从阻塞中退出...");
	               System.out.println("this.isInterrupted()="+this.isInterrupted());

	           }
	       }
	       System.out.println(getName()+"已经终止!");
	   }
	public static void main(String[] args) throws InterruptedException {
		ThreadTest ta=new ThreadTest();
	        ta.setName("ThreadA");
	        ta.start();
	        Thread.sleep(2000);
	        System.out.println(ta.getName()+"正在被中断...");
	        ta.interrupt();
	        System.out.println("ta.isInterrupted()="+ta.isInterrupted());

	}

}


什么情况,打断了为什么还能继续输出?

上面已经说过:interrupt 方法用来设置线程的中断状态,如果目标线程正阻塞于 wait、sleep 等方法时,首先会清除目前线程的中断状态,然后抛出 java.lang.InterruptedException异常

目标线程正在进行第 4 次循环,进入了 sleep 操作中,此时收到了主线程的 interrupt 操作,目标线程拥有了中断状态,则先清除中断状态,然后抛出异常,若是 catch 语句没有处理异常,则下一 次循环中 isInterrupted() 为false,线程会继续执行,可能 N 次抛出异常,也没法让线程中止。

那怎么停止当前线程呢?在线程同步的时候要有一个叫 二次惰性检测,能在提升效率的基础上又确保线程真正中同步控制中。那么把线程正确退出的方法称为 “双重安全退出”,不是以 isInterrupted () 为循环条件。而以一个标记做为循环条件。

public class ThreadTest extends Thread {
	private boolean isInterrupted=false;
	   int count=0;
	   
	   public void interrupt(){
	       isInterrupted = true;
	       super.interrupt();
	      }
	   
	   public void run(){
	       System.out.println(getName()+"将要运行...");
	       while(!isInterrupted){
	           System.out.println(getName()+"运行中"+count++);
	           try{
	               Thread.sleep(400);
	           }catch(InterruptedException e){
	               System.out.println(getName()+"从阻塞中退出...");
	               System.out.println("this.isInterrupted()="+this.isInterrupted());

	           }
	       }
	       System.out.println(getName()+"已经终止!");
	   }
	public static void main(String[] args) throws InterruptedException {
		ThreadTest ta=new ThreadTest();
	        ta.setName("ThreadA");
	        ta.start();
	        Thread.sleep(2000);
	        System.out.println(ta.getName()+"正在被中断...");
	        ta.interrupt();
	        System.out.println("ta.isInterrupted()="+ta.isInterrupted());

	}

}

执行结果如下:

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/704203.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号