java基础知识回顾之java Thread类学习-- 线程中断

Posted 积淀

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java基础知识回顾之java Thread类学习-- 线程中断相关的知识,希望对你有一定的参考价值。

官方文档翻译:

 

      如果本线程是处于阻塞状态:调用线程的wait(), wait(long)或wait(long, int)会让它进入等待(阻塞)状态,或者调用线程的join(), join(long), 

join(long, int), sleep(long), sleep(long, int)也会让它进入阻塞状态。若线程在阻塞状态时,调用了它的interrupt()方法,那么

它的“中断状态”会被清除并且会收到一个InterruptedException异常。例如,线程通过wait()进入阻塞状态,此时通过interrupt()中断该线程;

调用interrupt()会立即将线程的中断标记设为“true”,但是由于线程处于阻塞状态,所以该“中断标记”会立即被清除为“false”,同时,会产生一个InterruptedException的异常。

    如果线程被阻塞在一个Selector选择器中,那么通过interrupt()中断它时;线程的中断标记会被设置为true,并且它会立即从选择操作中返回。

    如果不属于前面所说的情况,那么通过interrupt()中断线程时,它的中断标记会被设置为“true”。中断一个“已终止的线程”不会产生任何操作。

 

线程处于“阻塞状态”和“运行状态”的终止方式如下:

(1)使用isInterrupted判断,使用interrupt中断

 

@Override
public void run() {
    try {
        // 1. isInterrupted()保证,只要中断标记为true就终止线程。
        while (!isInterrupted()) {
            // 执行任务...
        }
    } catch (InterruptedException ie) {  
        // 2. InterruptedException异常保证,当InterruptedException异常产生时,线程被终止。
    }
}

例子1:

package concurrentMy.interrupts;

/**
 * 
 * (interrupt()常常被用来终止“阻塞状态”线程。)
 *
 * <p>
 * 修改历史:                                            <br>  
 * 修改日期            修改人员       版本             修改内容<br>  
 * -------------------------------------------------<br>  
 * 2016年11月3日 下午2:56:44   user     1.0        初始化创建<br>
 * </p> 
 *
 * @author        Peng.Li 
 * @version        1.0  
 * @since        JDK1.7
 * 


运行结果:

A线程的状态: (NEW) is new
A线程的状态: (RUNNABLE) is start
A线程的状态: (RUNNABLE) loop 1
A线程的状态: (RUNNABLE) loop 2
A线程的状态: (TIMED_WAITING) is interrupted
A线程的状态: (RUNNABLE) catch InterruptedException.
A线程的状态: (TERMINATED) is interrupted now

结果说明:1.主线程通过    new ThreadMy("A")创建线程t1,之后之后通过t1.start()启动线程A。
        2.线程A启动之后,会不断的检查它的中断标识,如果中断标识为false,则休眠100ms
        3.t1休眠之后,会切换到主线程main,主线程再次运行,会执行t1.interrupt();中断A线程,
        A收到中断指令后,将A线程的中断标识设置成“false”,而且会抛出InterruptedException异常
 * 
 */

class ThreadMy extends Thread {

    public ThreadMy(String name) {
        super(name);
    }

    @Override
    public void run() {
        int i = 0;
        try {
            //1. isInterrupted()保证,只要中断标记为true就终止线程。
            while (!isInterrupted()) {
                //线程A休眠,进入阻塞状态
                Thread.sleep(100);
                i++;
                // 返回当前线程的状态
                System.out.println(Thread.currentThread().getName() + "线程的状态: (" + this.getState() + ") loop " + i);
            }
            
        } catch (InterruptedException e) {
            // 2. InterruptedException异常保证,当InterruptedException异常产生时,线程被终止。
            // TODO: handle exception
            System.out.println(Thread.currentThread().getName() + "线程的状态: (" + this.getState() + ") catch InterruptedException.");
        }

    }
}

public class Demo1_interrupt {
    public static void main(String[] args) {
        try {
            // 新建线程A
            ThreadMy t1 = new ThreadMy("A");
            System.out.println(t1.getName() + "线程的状态: (" + t1.getState() + ") is new");
            // 启动线程A
            t1.start();
            System.out.println(t1.getName() + "线程的状态: (" + t1.getState() + ") is start");
            // 主线程休眠300毫秒,然后main线程给t1发送指令
            Thread.sleep(300);
            t1.interrupt();
            
            System.out.println(t1.getName() + "线程的状态: (" + t1.getState() + ") is interrupted");

            // 主线程再休眠300ms,查看A线程的状态
            Thread.sleep(300);
            System.out.println(t1.getName() + "线程的状态: (" + t1.getState() + ") is interrupted now");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
}

(2)安全的终止线程,使用volatile boolean变量。

 

package concurrentMy.interrupts;

/**
 * 
 *
 * <p>
 * 修改历史:                                            <br>  
 * 修改日期            修改人员       版本             修改内容<br>  
 * -------------------------------------------------<br>  
 * 2016年11月3日 下午2:56:44   user     1.0        初始化创建<br>
 * </p> 
 *
 * @author        Peng.Li 
 * @version        1.0  
 * @since        JDK1.7
 * 

安全的终止线程,使用volatile boolean变量。

运行结果:

A线程的状态: (NEW) is new
A线程的状态: (RUNNABLE) is start
A线程的状态: (RUNNABLE) loop 1
A线程的状态: (RUNNABLE) loop 2
A线程的状态: (TIMED_WAITING) is interrupted
A线程的状态: (RUNNABLE) loop 3
count3
A线程的状态: (TERMINATED) is interrupted now


结果说明:1.主线程通过    new ThreadMy("A")创建线程t1,之后之后通过t1.start()启动线程A。
        2.线程A启动之后,会不断的检查它的中断标识,如果中断标识为true,则休眠100ms
        3.t1休眠之后,会切换到主线程main,主线程再次运行,会执行t1.cancel();中断A线程,
        A收到中断指令后,将A线程的中断标识设置成“false”,清除中断标识,而且会抛出InterruptedException异常
 * 
 * 
 *  
 */

class ThreadMy1 extends Thread {

    // volatile的应用,保证线程之间对on标识的可见性,一个线程(主线程)改了标识,
    // 即调用A线程的cancel方法取消或者停止了任务(A线程的执行,则立即对这个线程(A线程)可见
    private volatile boolean on = true;

    public ThreadMy1(String name) {
        super(name);
    }

    /**
     * 
     * (// 通过on 变量来控制是否需要停止任务并且终止任务) 
     *
     */
    public void cancel() {
        on = false;
    }

    @Override
    public void run() {
        int i = 0;
        try {
            // on = false 的时候中断线程
            while (on /* && !isInterrupted() */) {
                // 线程A休眠,进入阻塞状态
                Thread.sleep(100);
                i++;
                // 返回当前线程的状态
                System.out.println(Thread.currentThread().getName() + "线程的状态: (" + this.getState() + ") loop " + i);
            }
            System.out.println("count" + i);
        } catch (InterruptedException e) {
            // 2. InterruptedException异常保证,当InterruptedException异常产生时,线程被终止,这个地方加一些日志操作
            // TODO: handle exception
            System.out.println(Thread.currentThread().getName() + "线程的状态: (" + this.getState() + ") catch InterruptedException.");
        }

    }
}

public class Demo2_interrupt {
    public static void main(String[] args) {
        try {
            // 新建线程A
            ThreadMy1 t1 = new ThreadMy1("A");
            System.out.println(t1.getName() + "线程的状态: (" + t1.getState() + ") is new");
            // 启动线程A
            t1.start();
            System.out.println(t1.getName() + "线程的状态: (" + t1.getState() + ") is start");
            // 主线程休眠300毫秒,然后main线程给t1发送指令
            Thread.sleep(300);
            // 中断线程
            t1.cancel();
            System.out.println(t1.getName() + "线程的状态: (" + t1.getState() + ") is interrupted");

            // 主线程再休眠300ms,查看A线程的状态
            Thread.sleep(300);
            System.out.println(t1.getName() + "线程的状态: (" + t1.getState() + ") is interrupted now");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
}

 

 

以上是关于java基础知识回顾之java Thread类学习-- 线程中断的主要内容,如果未能解决你的问题,请参考以下文章

java多线程知识回顾

Java集合之Collection与之子类回顾

一脚踩进java之基础篇43——线程Thread和Runnable

一脚踩进java之基础篇43——线程Thread和Runnable

Java基础知识回顾之三 ----- 封装继承和多态

Java基础知识回顾之三 ----- 封装继承和多态