一 中断线程
1.1 中断概念
1.在java中,没有提供一种立即停止一条线程。但却给了停止线程的协商机制-中断。
中断是一种协商机制。中断的过程完全需要程序员自己实现。也即,如果要中断一个线程,你需要手动调用该线程的interrupt()方法,该方法也仅仅是将线程对象中的中断标识设置成true;接着需要自己在方法中手动判断当前线程的标识位,如果为true,则中断线程。false标识未中断。
2.一个线程不应该由其他线程中断或者停止,而是有该线程自己自行停止,自己决定命运。
stop(),suspend,resume方法都已经废弃。
1.2 interrupt和isinterrupted和interrupted的作用
1.public void interrupt(): 实例方法,仅仅是设置线程中断状态为true,发起一个协商而不会立刻停止线程。
2.public static boolean interrupted;静态方法,判断当前线程是否中断并清除当前线程的中断状态。做两件事:
a)返回当前线程的中断状态,测试当前线程是否已经中断。
b)将当前线程的中断状态清零并重新设置为true,清除线程的中断状态。
3.public boolean isinterrupted():实例方法判断当前线程是不是中断,检测中断标志位。
1.3 interrupt的使用情况分析
当对一个线程,调用interrupt()时:
1.如果线程处于正常活动状态,那么会将该线程的中断标志设置为true,仅此而已。
被设置中断标志的线程将继续正常运行,不受影响。
interrupt()并不能真正中断线程,需要被调用的线程自己进行配合才行。
2.如果线程处于被阻塞状态(sleep,wait,join等状态),在别的线程中调用当前线程对象的interrupt方法,那么线程将立即退出被阻塞的状态,并抛出一个interruptedException异常。
二 中断线程方式
2.1 方式1 通过volatile变量
package com.ljf.thread.interrupt;import java.util.concurrent.atomic.AtomicBoolean;/*** @ClassName: Zhongduan2* @Description: TODO* @Author: admin* @Date: 2024/03/02 17:43:01 * @Version: V1.0**/
public class Zhongduan2 {public static volatile boolean flag=false;static AtomicBoolean atomicBoolean = new AtomicBoolean(false);public static void main(String[] args) throws InterruptedException {Thread t1= new Thread(new Runnable() {@Overridepublic void run() {while(true){if(flag){// if(atomicBoolean.get()){System.out.println("===================开始中断"+Thread.currentThread().getId());break;}else{System.out.println("循环中:"+Thread.currentThread().getId());}}}});t1.start();//主线程先休眠2秒Thread.sleep(5000);new Thread(new Runnable() {@Overridepublic void run() {flag=true;atomicBoolean.set(true);}}).start();}}
2.2 方式2 通过atomicboolean 原子类
public static volatile boolean flag=false;static AtomicBoolean atomicBoolean = new AtomicBoolean(false);public static void main(String[] args) throws InterruptedException {Thread t1= new Thread(new Runnable() {@Overridepublic void run() {while(true){// if(flag){if(atomicBoolean.get()){System.out.println("===================开始中断"+Thread.currentThread().getId());break;}else{System.out.println("循环中:"+Thread.currentThread().getId());}}}});t1.start();//主线程先休眠2秒Thread.sleep(5000);new Thread(new Runnable() {@Overridepublic void run() {flag=true;atomicBoolean.set(true);}}).start();}
2.3 方式3 通过interrupt+isinterrupted组合判断
package com.ljf.thread.interrupt;/*** @ClassName: Zhongduan* @Description: TODO* @Author: admin* @Date: 2024/03/02 17:34:59 * @Version: V1.0**/
public class Zhongduan {public static volatile boolean flag=false;public static void main(String[] args) throws InterruptedException {Thread t1= new Thread(new Runnable() {@Overridepublic void run() {while(true){if(Thread.currentThread().isInterrupted()){System.out.println("===================开始中断"+Thread.currentThread().getId());break;}else{System.out.println("循环中:"+Thread.currentThread().getId());}}}});t1.start();//主线程先休眠2秒Thread.sleep(5000);new Thread(new Runnable() {@Overridepublic void run() {t1.interrupt();}}).start();}
}
三 中断线程方式的情况分析
3.1 情况1
如果线程处于被阻塞状态(sleep,wait,join等状态),在别的线程中调用当前线程对象的interrupt方法,那么线程将立即退出被阻塞的状态,并抛出一个interruptedException异常。
public static void main(String[] args){//实例方法interrupt()仅仅是设置线程的中断状态位设置为true,不会停止线程Thread t1 = new Thread(() -> {for (int i = 1; i <=300; i++){System.out.println("-----: "+i);}System.out.println("t1线程调用interrupt()后的的中断标识02:"+Thread.currentThread().isInterrupted());}, "t1");t1.start();System.out.println("t1线程默认的中断标识:"+t1.isInterrupted());//false//暂停毫秒try { TimeUnit.MILLISECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); }t1.interrupt();//trueSystem.out.println("t1线程调用interrupt()后的的中断标识01:"+t1.isInterrupted());//truetry { TimeUnit.MILLISECONDS.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); }System.out.println("t1线程调用interrupt()后的的中断标识03:"+t1.isInterrupted());//---false中断不活动的线程不会产生任何影响。}
线程t1执行300次后,已经不存在,2秒后查看t1线程的状态为false。
3.2 情况2
1.代码
public class InterruptDemo3
{public static void main(String[] args){Thread t1 = new Thread(() -> {while (true){if(Thread.currentThread().isInterrupted()){System.out.println(Thread.currentThread().getName()+"\t " +"中断标志位:"+Thread.currentThread().isInterrupted()+" 程序停止");break;}try {Thread.sleep(200);} catch (InterruptedException e) {Thread.currentThread().interrupt();//为什么要在异常处,再调用一次??e.printStackTrace();}System.out.println("-----hello InterruptDemo3");}}, "t1");t1.start();//暂停几秒钟线程try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); }new Thread(() -> t1.interrupt(),"t2").start();}
}
问题:报异常,程序没有停止
2.分析原因
* 1 中断标志位,默认false * 2 t2 ----> t1发出了中断协商,t2调用t1.interrupt(),中断标志位true * 3 中断标志位true,正常情况,程序停止,^_^ * 4 中断标志位true,执行sleep 后发生异常情况,InterruptedException,将会把中断状态将被清除,并且将收到InterruptedException 。中断标志位false * 导致无限循环 * * 5 在catch块中,需要再次给中断标志位设置为true,2次调用停止程序才OK
3.结论
3.3 情况3 关闭线程
https://blog.51cto.com/u_13316945/5832262
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);Future future = fixedThreadPool.submit(new Runnable() { @Override public void run() {
new Runnable() {@Overridepublic void run() {/** 确保线程不断执行不断刷新界面*/while (true&&(!Thread.currentThread().isInterrupted())) {try {Log.i("tag","线程运行中"+Thread.currentThread().getId());// 每执行一次暂停40毫秒//当sleep方法抛出InterruptedException 中断状态也会被清掉Thread.sleep(40);} catch (InterruptedException e) {e.printStackTrace();//如果抛出异常则再次设置中断请求Thread.currentThread().interrupt();}}}}
);
//触发条件设置中断
future.cancel(true);