有这样一个场景,用户下载一个文件,由于网速比较慢,下载了一部分,想退出,不下想下载了,这时就需要我们的中断机制。

中断机制就是通知线程,让线程有一个中断的状态,对于线程对中断的识别,线程在不同的状态下可以对中断的处理也不是一样。这里涉及线程的几种状态,又不是很熟悉的可以查一下。

这里涉及的线程如下:

这个线程测试开始,运行的状态

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,线程异常抛出。