interrupt()方法
——interrupt()方法并不是中断线程,而是中断阻塞状态,或者将线程的[中断标志位]置为true。
——对于未阻塞的线程,interrupt()只是造成[中断标志位]=true,线程本身运行状态不受影响。
——对于阻塞的线程,interrupt()会中断阻塞状态,使其转换成非阻塞状态,并清除[中断标志位]。
——造成阻塞状态的情况有:sleep()、wait()和join()。
——阻塞状态的线程被中断时,只是中断了阻塞状态,即sleep()、wait()和join(),线程本身还在继续运行。
实例演示
1 非阻塞线程调用interrupt()方法 只是将中断标志位设置为true 不会影响线程正常运行
public class interrupteDemo {
private static final Logger LOGGER=Logger.getAnonymousLogger();
public static void main(String[] args) {
// TODO Auto-generated method stub
LOGGER.info("interrupt()并不是中断线程 而是将线程中断标志位设置为true");
new Thread(
()->
{
Thread thread=Thread.currentThread();
for(int i=0;i<5;i++)
{
LOGGER.info("线程"+thread.getName()+"i="+i+"isInterrupted="+thread.isInterrupted());;
if(i==2)
{
thread.interrupt();
}
}
LOGGER.info("线程"+thread.getName()+"停止运行"+"isInterrupted="+thread.isInterrupted());
}
).start();
}
}
2 通过interrupt()与isInterrupted()控制for循环的运行状态(非阻塞线程) 即根据中断标志位 进行控制
new Thread(
()->
{
Thread thread=Thread.currentThread();
for(int i=0;i<5&&!thread.isInterrupted();i++)
{
LOGGER.info("线程"+thread.getName()+"i="+i+"isInterrupted="+thread.isInterrupted());;
if(i==2)
{
thread.interrupt();
}
}
LOGGER.info("线程"+thread.getName()+"停止运行"+"isInterrupted="+thread.isInterrupted());
}
).start();
可以看到执行到i=2之后不在执行
3 阻塞线程(sleep/wait/joni)中的while循环应用interrupt()和isInterrupted()
System.out.println();
LOGGER.info("在有阻塞状态(sleep/wait/joni)的while循环中应用interrupt()和isInterrupted()");
Thread thread2 = new Thread(() -> {
//如果当前线程没被中断,则一直进行
while (!Thread.currentThread().isInterrupted()) {
LOGGER.info("线程[" + Thread.currentThread().getName() + "]正在运行...");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
LOGGER.info("线程[" + Thread.currentThread().getName() + "]停止运行");
});
thread2.start();
Thread.sleep(200);
thread2.interrupt();
创建了thread2执行run后 由于sleep睡眠5秒 进入阻塞态
而主线程调用 thread2.interrupt将修改thread2的中断位
使得还在5秒钟睡眠时间内的线程被打断 抛出异常
但是程序还是会继续运行
由此可以发现这种方式 并不能跳出循环 不是想要的结果
解决方案: 将catch块外移动
Thread thread2 = new Thread(() -> {
//如果当前线程没被中断,则一直进行
try {
while (!Thread.currentThread().isInterrupted()) {
LOGGER.info("线程[" + Thread.currentThread().getName() + "]正在运行...");
Thread.sleep(5000);
}
}catch (InterruptedException e) {
LOGGER.info("线程[" + Thread.currentThread().getName() + "]停止运行");
}
});
thread2.start();
Thread.sleep(200);
thread2.interrupt();
可以看到成功的在调用interrupt之后结束循环
由此可见对阻塞线程的控制一般方法
//在线程定义类中
@Override
public void run(){
try{
//阻塞代码:sleep、join和wait
}catch(InterruptedException e){
//注释掉e.printStackTrace();
//添加其他业务代码
}
}
//在线程使用时
thread.interrupt();