有这样一个场景,用户下载一个文件,由于网速比较慢,下载了一部分,想退出,不下想下载了,这时就需要我们的中断机制。
中断机制就是通知线程,让线程有一个中断的状态,对于线程对中断的识别,线程在不同的状态下可以对中断的处理也不是一样。这里涉及线程的几种状态,又不是很熟悉的可以查一下。
这里涉及的线程如下:
这个线程测试开始,运行的状态
package juc.thread;
/**
* @Description
* @Author DJZ-WWS
* @Date 2019/5/14 19:59
*/
public class MyThread extends Thread {
@Override
public void run() {
while(true){
if (Thread.currentThread().isInterrupted()){
//一旦线程被中断,立即退出死循环
System.out.println("exit MyThread");
break;
}
}
}
}
这个线程是测试阻塞状态,使用同步锁实现线程阻塞
package juc.thread;
/**
* @Description 测试线程处于阻塞状态时中断的情况
* @Author DJZ-WWS
* @Date 2019/5/14 20:23
*/
public class MyThread2 extends Thread{
public synchronized static void doSomething(){
while(true){
//do something
}
}
@Override
public void run() {
doSomething();
}
}
这个线程测试等待状态
package juc.thread;
/**
* @Description
* @Author DJZ-WWS
* @Date 2019/5/14 20:41
*/
public class MyThread3 extends Thread{
@Override
public void run(){
synchronized (this){
try {
wait();
} catch (InterruptedException e) {
System.out.println("i am waiting but facing interruptexception now");
}
}
}
}
具体的测试 如下,具体的分析在每个测试demo上面都有具体的说明。
package juc.thread;
import org.junit.Test;
/**
* @Description
* @Author DJZ-WWS
* @Date 2019/5/14 20:00
*/
public class ThreadTest {
/**
* Terminated和NEW状态的线程对于java来说毫无意义,什么事也不会发生。
* <p>
* 测试线程的中断在new状态的时候中断标记
*/
@Test
public void testNEW() {
//处于就绪的状态
Thread thread = new MyThread();
System.out.println(thread.getState());//new
thread.interrupt();
System.out.println(thread.isInterrupted()); //false
}
/**
* //TERMINATED表示线程已经终止
*
* @throws InterruptedException
*/
@Test
public void testTerminated() throws InterruptedException {
Thread thread = new MyThread();
thread.start();
thread.join();
System.out.println(thread.getState()); //TERMINATED
thread.interrupt();
System.out.println(thread.isInterrupted()); //false
}
/**
* 如果线程处于运行状态,那么对于状态就是Runnable的状态,但是不是所有的Runnable状态都能获得CPU运行,
* 在某个时间段,只能由一个线程占用cpu,那么其余的线程虽然状态是Runnable,但是都没有处于运行状态。
* 而我们处于Runnable状态的线程在遭遇中断操作的时候只会设置该线程的中断标志位。
* 处理的思路在run方法里加上判断,如果该线程被中断标记了,直接break。
*
* @throws InterruptedException
*/
@Test
public void testRUNNABLE() throws InterruptedException {
Thread thread = new MyThread();
thread.start();
System.out.println(thread.getState()); //TERMINATED
thread.interrupt();
Thread.sleep(1000);//等到thread线程被中断之后
System.out.println(thread.isInterrupted());//false
System.out.println(thread.getState()); //再break循环以后状态变为TERMINATED
}
/**
* 定义了两个线程并且按照定义的顺序启动他们,thread1启动后直接占用锁资源,thread2进入了队列,thread自然的处于阻塞状态,
* 但是我们执行了中断操作,虽然thread2处于阻塞,中断标记为true,这样我们可以通过这个特性去灵活的处理
* 测试线程处于阻塞状态时中断情况
*/
@Test
public void testBLOCKED() throws InterruptedException {
Thread thread1 = new MyThread2();
Thread thread2 = new MyThread2();
thread1.start();
thread2.start();
Thread.sleep(2000);
System.out.println(thread1.getState());
System.out.println(thread2.getState());
thread2.interrupt();//线程2中断
System.out.println(thread2.isInterrupted());//true 线程虽然处于阻塞,但是还是true
System.out.println(thread2.getState());//BLOCKED
}
/**
* WAITING则是无限期等待,需要其他线程调用notify方法释放自己
* TIMED_WAITING在等待一段时间后会自动释放自己
* 这些线程在遇到中断的时候会抛出一个InterrruptedException,并清空中断标志位
*/
@Test
public void testWAITINGAndTIMED_WAITING() throws InterruptedException {
Thread thread = new MyThread3();
thread.start();
Thread.sleep(500);
System.out.println(thread.getState());//WAITING
thread.interrupt();
Thread.sleep(1000);
System.out.println(thread.isInterrupted());//false
System.out.println(thread.getState());//异常以后程序终止了
}
/**
* 线程的生命周期
*/
}
总结:线程中断就是告知某个线程你需要停下来了,但是由于处在不同的状态NEW,Terminated这两个状态对于线程来说没意义,一个线程处于NEW,就绪还未启动,一个是已经终止。RUNNABLE运行状态,一般都会通过获取他的状态,通过break去退出一个循环。BLOCKED阻塞状态,线程在一个队里里进行等待,如果处于阻塞,那么他的中断标记还是true。AITING或者TIMED_WAITING一个是一直处于等待,直到被唤醒,一个是等待指定时间,执行中断以后,中断状态变为false,线程异常抛出。