java中如何中断thread

时间:2022-11-22 17:34:54

要中断thread的执行,我们有多种方式,有些方式是推荐的,有些方式是不推荐的,甚至是错误的。


1. 可否用interrupt()方法来中断thread?

为了回答这个问题,我们首先来看一个例子:

class MyThread implements Runnable {

	public void run() {
		while (true) {
			System.out.println("Mythread am running!, current interrupted status is " + Thread.currentThread().isInterrupted());
		}
	}
}

public class InterruptTaskTest {

	public static void main(String[] args) {
		Thread thread = new Thread(new MyThread());
		thread.start(); // start mythread
		//
		try {
			Thread.sleep(100); // the main thread sleeps for 100 miniseconds
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("Main thread tries to interrupt mythread!");
		thread.interrupt(); // "interrupt" mythread
	}
}
输出:

Mythread is running!, current interrupted status is false
Main thread tries to interrupt mythread!
Mythread is running!, current interrupted status is true

Mythread is running!, current interrupted status is true
Mythread is running!, current interrupted status is true
Mythread is running!, current interrupted status is true

Mythread is running!, current interrupted status is true

从上面的结果可以看出,调用interrupt方法并不能使得一个thread终止,但是这个方法可以改变线程是否被终止的状态为true. 用一句社会上的话来讲就是”不错,老子是欠你钱,但是老子就是不还“。

既然线程的状态已经改变,那么我们可以加入下面一句话来让线程停止。

class MyThread implements Runnable {

	public void run() {
		while (true) {
			System.out.println("Mythread is running!, current status is " + Thread.currentThread().isInterrupted());
<strong>			<span style="color:#ff0000;">if (Thread.currentThread().isInterrupted()) {
				System.out.println("Mythread stops");
				return;
			}</span></strong>
		}
	}
}

public class InterruptTaskTest {

	public static void main(String[] args) {
		Thread thread = new Thread(new MyThread());
		thread.start(); // start mythread

		try {
			Thread.sleep(50);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("Main thread tries to interrupt mythread!");
		thread.interrupt(); // "interrupt" mythread

	}
}

输出是:

Mythread is running!, current status is false
Mythread is running!, current status is false
Mythread is running!, current status is false
Main thread tries to interrupt mythread!
Mythread is running!, current status is false
Mythread is running!, current status is true
Mythread stops

你如果运行上面的代码,得到的结果有可能是:

Mythread is running!, current status is false
Mythread is running!, current status is false
Mythread is running!, current status is false
Main thread tries to interrupt mythread!
Mythread is running!, current status is false
Mythread stops

原因是当mythread打印 ”Mythread is running!, current status is false“这句话的时候,main thread并没有执行下面代码,

thread.interrupt();

如果当上面语句被执行以后,mythread执行if 条件语句,那么最后会输出 ”Mythread stops“。


从上面这个例子可以看出,通过interrupt()方法,我们还是可以让一个线程终止的。但是我们是不是就可以认为这是一个好的方法呢?回答是NO。因为interrupt方法里面有很多的陷阱,先读读下面这段话:

If this thread is blocked in an invocation of the wait(), wait(long), or wait(long, int) methods of the Object class, or of the join(), join(long), join(long, int), sleep(long), or sleep(long, int), methods of this class, then its interrupt status will be cleared and it will receive an InterruptedException.

上面这句话的意思是如果线程处于阻塞状态(可能是因为调用了wait,join,sleep的原因),那么,如果你调用interrupt方法,那么你惨了,因为interrupt状态会被清除并且被抛出异常。如果你不理解这句话,看看下面的代码:

class MyThread implements Runnable {

	public void run() {
		while (true) {
			System.out.println("Mythread is running!, current status is " + Thread.currentThread().isInterrupted());

<span style="color:#ff0000;">			try {
				System.out.println("Mythread starts to sleep!");
				Thread.sleep(1000);
				System.out.println("Mythread wakes up!");
			} catch (InterruptedException e) {
				System.out.println("Throws exception!, current status is " + Thread.currentThread().isInterrupted());
			}</span>

			if (Thread.currentThread().isInterrupted()) {
				System.out.println("Mythread stops");
				return;
			}
		}
	}
}

public class InterruptTaskTest {

	public static void main(String[] args) {
		Thread thread = new Thread(new MyThread());
		thread.start(); // start mythread
		try {
			Thread.sleep(2);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("Main thread tries to interrupt mythread!");
		thread.interrupt(); // "interrupt" mythread
	}
}

输出结果是:

Mythread is running!, current status is false
Mythread starts to sleep!
Main thread tries to interrupt mythread!
Throws exception!, current status is false
Mythread is running!, current status is false
Mythread starts to sleep!
Mythread wakes up!
Mythread is running!, current status is false
Mythread starts to sleep!
Mythread wakes up!
Mythread is running!, current status is false
Mythread starts to sleep!
Mythread wakes up!
Mythread is running!, current status is false
Mythread starts to sleep!
Mythread wakes up!
Mythread is running!, current status is false

从结果中可以看出,发生异常后,interrupt status 居然不是true, 即便interrupt方法已经调用了,所以后面部分的if 条件始终是false,线程最后没有能够停下来。

2. 什么是一种比较好的让线程停下来的方法呢?

方法代码如下:

public class MyThread implements Runnable {

	private volatile boolean isRunning = true;

	public void run() {

		while (isRunning) {
			// do work
		}
	}

	public void kill() {
		isRunning = false;
	}
}

从上面代码可以看出,这里使用了一个bool变量 isRunning, 通过kill方法,使得isRunning的值变为false, 从而使得while loop停止。我们用volatile修饰 isRunning是保证如果有多个线程使用isRunning值的话,isRunning的值是及时更新的。

转载请注明出处: blog.csdn.net/beiyetengqing