interrupt方法用于中断线程。调用该方法的线程的状态为将被置为"中断"状态。
当线程被阻塞的时候,比如被Object.wait, Thread.join和Thread.sleep三种方法之一阻塞时。
调用它的interrput()方法。没有占用CPU运行的线程是不可能给自己的中断状态置位的。这就会产生一个InterruptedException异常,并且不会设置中断状态
Interrupted的经典使用代码:
// Interrupted的经典使用代码
public void run(){
try{
....
while(!Thread.currentThread().isInterrupted()&& more work to do){
// do more work;
}
}catch(InterruptedException e){
// thread was interrupted during sleep or wait
}
finally{
// cleanup, if required
}
}
但是对于sleep,wait,join 要如下处理:
private static void test5() throws Exception{
Thread t = new Thread (){
public void run(){
while(!Thread.currentThread().isInterrupted()){
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
//这里因为线程已经在运行了,所以可以设置中断状态,
//并且下次Thread.currentThread().isInterrupted() 会返回true
Thread.currentThread().interrupt();
e.printStackTrace();
}
if(Thread.currentThread().isInterrupted()){
System.out.println("Someone interrupted me.");
}
else{
System.out.println("Thread is Going...");
}
}
}
} ;
t.start();
Thread.sleep(3000);
//此时,线程在sleep,虽然被打断,仅仅是抛出异常从sleep中退出,不会设置中断状态
t.interrupt();
}
private static void test6() throws Exception{
Thread t = new Thread (){
public synchronized void run(){
while(!Thread.currentThread().isInterrupted()){
try {
System.out.println("wait");
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println();
//false
System.out.println(Thread.currentThread().isInterrupted());
//这里因为线程已经在运行了,所以可以设置中断状态,
//并且下次Thread.currentThread().isInterrupted() 会返回true
Thread.currentThread().interrupt();
}
if(Thread.currentThread().isInterrupted()){
System.out.println("Someone interrupted me.");
}
else{
System.out.println("Thread is Going...");
}
}
}
} ;
t.start();
Thread.sleep(3000);
//此时,线程在sleep,虽然被打断,仅仅是抛出异常从sleep中退出,不会设置中断状态
t.interrupt();
}
下面的案例说明了这个问题:
wait响应中断,会抛出异常,但是不会设置中断状态
/**
* wait响应中断,会抛出异常,但是不会设置中断状态
*/
private static void testWait() throws Exception {
Thread t = new Thread(){
public synchronized void run() {
try {
System.out.println("internal thread running");
this.wait();
System.out.println("internal thread over");
} catch (InterruptedException e) {
e.printStackTrace();
}
//false
System.out.println(Thread.currentThread().isInterrupted());
};
};
t.start();
SleepUtils.sleep(1000);
t.interrupt();
System.out.println(t.isInterrupted());
System.out.println("Main over");
}
park的被中断后,不会抛出异常,另外会设置中断位
/**
* park响应中断,但是不会抛出异常
*/
private static void testPark() throws Exception {
Thread t = new Thread(){
public void run() {
System.out.println("internal thread running");
LockSupport.park(Thread.currentThread());
System.out.println("internal thread over");
//true
System.out.println(Thread.currentThread().isInterrupted());
};
};
t.start();
SleepUtils.sleep(3000);
t.interrupt();
System.out.println("Main over");
}
sleep 会抛出异常,但是不会设置中断状态
中断之后,再调用sleep 会抛出异常,并清理中断状态 (这里指 Thread.currentThread().interrupt())
/**
* sleep响应中断,会抛出异常,设置中断状态
* @throws Exception
*/
private static void testSleep() throws Exception {
Thread t = new Thread(){
public void run() {
try {
System.out.println("internal thread running");
Thread.currentThread().sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//false
System.out.println("----"+Thread.currentThread().isInterrupted());
};
};
t.start();
SleepUtils.sleep(3000);
t.interrupt();
System.out.println("Main over");
}
运行中的线程,中断线程,不会终止线程的执行,只是改变了中断状态
/**
* 运行中的线程,打断,不会终止线程的执行,只是改变了中断状态
* 对于非阻塞中的线程, 只是改变了中断状态
*/
private static void test1() throws Exception{
Thread t = new Thread (){
public void run(){
while(true){
if(Thread.currentThread().isInterrupted()){
System.out.println("Someone interrupted me.");
}
else{
System.out.println("Thread is Going...");
}
}
}
} ;
t.start();
Thread.sleep(3000);
t.interrupt();
/**
分析如上程序的结果:
在main线程sleep的过程中由于t线程中isInterrupted()为false所以不断的输出”Thread is going”。
当调用t线程的interrupt()后t线程中isInterrupted()为true。此时会输出Someone interrupted me.
而且线程并不会因为中断信号而停止运行。因为它只是被修改一个中断信号而已。
当我们调用t.interrput()的时候,线程t的中断状态(interrupted status) 会被置位。
我们可以通过Thread.currentThread().isInterrupted() 来检查这个布尔型的中断状态。
*/
}
如果线程被Object.wait, Thread.join和Thread.sleep三种方法之一阻塞,那么,
它将接收到一个中断异常;如果线程被上述几种方法阻塞,正确的停止线程方式是设置共享变量,并调用interrupt()
private static void test2() throws Exception {
Thread3 thread = new Thread3();
System.out.println("Starting thread...");
thread.start();
Thread.sleep(3000);
System.out.println("Asking thread to stop...");
/*
* 如果线程阻塞,将不会检查此变量,调用interrupt之后,线程就可以尽早的终结被阻 塞状 态,能够检查这一变量。
*/
thread.stop = true;
/*
* 这一方法实际上完成的是,在线程受到阻塞时抛出一个中断信号,这样线程就得以退 出阻 塞的状态
*/
thread.interrupt();
Thread.sleep(3000);
System.out.println("Stopping application...");
System.exit(0);
}
static class Thread3 extends Thread {
volatile boolean stop = false;
public void run() {
while (!stop) {
System.out.println("Thread running...");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// 接收到一个中断异常(InterruptedException),从而提早地终结被阻塞状态
e.printStackTrace();
System.out.println("Thread interrupted...");
}
}
System.out.println("Thread exiting under request...");
}
}