java-interrupt方法的一个小的注意点_夜行过客-编程思维

Java-interrupt方法的一个小的注意点

记录Java 中 interupt() 方法的一个小的知识点。

开发过程中,经常有需要去终止线程,终止线程的方式无外乎有两种 标志位 或 interrupt(), 前者没什么好说的,就是定义一个bool类型的变量,只是需要注意将该变量声明成 volatile。后者的话主要用于终止带阻塞状态的线程,当然也可以用来终止不带阻塞状态的线程,这里再来复习一下:

关于终止线程的介绍,可参考:Java: Java终止线程的几种方式

终止不带阻塞状态的线程

TaskCase.java

package com.yongdaimi.dmeo;


public class TaskCase {

	private Thread mTaskThread;
	
	public void start() {
		mTaskThread = new Thread() {
			
			@Override
			public void run() {
				super.run();
				
				System.out.println(Thread.currentThread().getName()+" start running...");
				
				// 模拟重复执行的任务
				while (!Thread.currentThread().isInterrupted()) {
					System.out.println("doSomething");
				}
				
				System.out.println(Thread.currentThread().getName()+" stop running...");
				
			}
			
		};
		mTaskThread.start();
	}
	
	/**
	 * 使用此方法进行终止
	 */
	public void calcel() {
		mTaskThread.interrupt();
	}
	
	
}

Test.java

package com.yongdaimi.dmeo;

public class Test {

	public static void main(String[] args) {
		
		
		TaskCase task = new TaskCase();
		task.start();
		
		// 2s 后将测试线程终止
		try {
			Thread.currentThread().sleep(2000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		task.calcel();
		
	}
	
}

运行:

doSomething
doSomething
doSomething
doSomething
doSomething
doSomething
doSomething
doSomething
doSomething
doSomething
doSomething
doSomething
doSomething
doSomething
doSomething
doSomething
doSomething
doSomething
doSomething
doSomething
doSomething
doSomething
doSomething
doSomething
doSomething
Thread-0 stop running...

可以看到使用此方法,2秒后是可以将执行线程正常终止的。

那如果加了阻塞状态呢?

TaskCase.java

package com.yongdaimi.dmeo;


public class TaskCase {

	private Thread mTaskThread;
	
	public void start() {
		mTaskThread = new Thread() {
			
			@Override
			public void run() {
				super.run();
				
				System.out.println(Thread.currentThread().getName()+" start running...");
				
				// 模拟重复执行的任务
				while (!Thread.currentThread().isInterrupted()) {
					System.out.println("doSomething");
					
					// 模拟阻塞 500ms
					try {
						Thread.currentThread().sleep(500);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
				
				System.out.println(Thread.currentThread().getName()+" stop running...");
				
			}
			
		};
		mTaskThread.start();
	}
	
	/**
	 * 使用此方法进行终止
	 */
	public void calcel() {
		mTaskThread.interrupt();
	}
	
	
}

这里在线程中添加一段code, 使线程临时阻塞500ms, 再次执行:

这时发现虽然有走到异常的代码块里,但是线程仍然能够正常执行,没有退出,Why? 这是因为:

「注意:发生异常时线程的中断标志为会由true更改为false。」

所以最好这样写成这样:

// 模拟重复执行的任务
				while (!Thread.currentThread().isInterrupted()) {
					System.out.println("doSomething");
					
					// 模拟阻塞 500ms
					try {
						Thread.currentThread().sleep(500);
					} catch (InterruptedException e) {
						e.printStackTrace();
						// 重置中断标志位为true
	                    Thread.currentThread().interrupt();
					}
				}

在出现异常后,重置中断标志位,这样再次执行后,就可以顺利中断线程了:

当然也可以在出现异常时,直接使用return语句终止,那样也是可以的,今天在是review一个同事的code时发现了此问题,所以记录一下。

参考链接:

为什么说volatile+interrupt是停止线程最优雅的姿势?

版权声明:本文版权归作者所有,遵循 CC 4.0 BY-SA 许可协议, 转载请注明原文链接
https://www.cnblogs.com/yongdaimi/p/16969091.html

java多线程-线程关键字(二)_佛祖让我来巡山-编程思维

Java中和线程相关的关键字就两:volatile和synchronized。 volatile以前用得较少,以后会用得更少(后面解释)。它是一种非常轻量级的同步机制,它的三大特性是: 1、保证可见性,即强制将CPU高速缓存的数据立即写入主存,会导致其他CPU核中对应的高速缓存内容无效,就像这样:   如果由于同步需

java多线程(2):线程关键字_湘王-编程思维

您好,我是湘王,这是我的博客园,欢迎您来,欢迎您再来~   Java中和线程相关的关键字就两:volatile和synchronized。 volatile以前用得较少,以后会用得更少(后面解释)。它是一种非常轻量级的同步机制,它的三大特性是: 1、保证可见性,即强制将CPU高速缓存的数据立即写入主存,会导致其他CPU

个人文章-编程思维

什么是volatile关键字volatile是Java中用于修饰变量的关键字,其可以保证该变量的可见性以及顺序性,但是无法保证原子性。更准确地说是volatile关键字只能保证单操作的原子性, 比如x=1 ,但是无法保证复合操作的原子性,比如x++其为Java提供了一种轻量级的同步机制:保证被volatile修饰的共享

(转)java并发编程:volatile关键字解析-编程思维

Java并发编程:volatile关键字解析    volatile这个关键字可能很多朋友都听说过,或许也都用过。在Java 5之前,它是一个备受争议的关键字,因为在程序中使用它往往会导致出人意料的结果。在Java 5之后,volatile关键字才得以重获生机。   volatile关键字虽然从字面上理解起来比较简单,