线程知识学习三(线程的“打断”)
interrupt的三个方法
1、interrupt():打断某个线程(设置线程中断标志位)
2、isInterrupted():查询某个线程是否被打断过(查询中断标志位)
3、static interrupted():查询当前线程是否被打断过,并重置打断标志
public class Interrupt_and_isInterrupted {
public static void main(String[] args) {
Thread t = new Thread(() -> {
for (; ; ) {
//此处查询标志位是否已经被打断过
if (Thread.currentThread().isInterrupted()) {
System.out.println("Thread is interrupted!");
System.out.println(Thread.currentThread().isInterrupted());
break;
}
}
});
t.start();
SleepHelper.sleepSeconds(2);
//此处设置标志位
t.interrupt();
}
}
运行结果如下:
Interrupt and Interrupted:
public class Interrupt_and_interrupted {
public static void main(String[] args) {
Thread t = new Thread(() -> {
for (; ; ) {
//查询标志位 true代表已打断
if (Thread.currentThread().isInterrupted()) {
System.out.println(Thread.currentThread().isInterrupted());
break;
}
}
for (; ; ) {
//判断并重置标志位
if (Thread.interrupted()) {
System.out.println("Thread is interrupted!");
System.out.println(Thread.interrupted());
//这里输出标志位为false代表重置标志位
}
}
});
t.start();
SleepHelper.sleepSeconds(2);
//设置标志位
t.interrupt();
}
}
输出结果如下:
线程执行sleep、wait、join方法时,如果线程被打断都会抛出一个interruptedException,Java会默认重置标志位(因为此处别人可能再次调用interrupt方法,这个打断的状态也需要被捕获到),然后再做后续业务处理。
interrupt and sleep:
public class Interrupt_and_sleep {
public static void main(String[] args) {
Thread t = new Thread(() -> {
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
System.out.println("Thread is interrupted!");
System.out.println(Thread.currentThread().isInterrupted());
}
});
t.start();
SleepHelper.sleepSeconds(5);
t.interrupt();
}
}
运行结果如下:
同理wait方法和join方法也是这样。
public class Interrupt_and_sync {
private static Object o = new Object();
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
synchronized (o) {
SleepHelper.sleepSeconds(10);
}
});
t1.start();
SleepHelper.sleepSeconds(1);
Thread t2 = new Thread(() -> {
synchronized (o) {
}
System.out.println("t2 end!");
});
t2.start();
SleepHelper.sleepSeconds(1);
t2.interrupt();
}
}
如上程序是线程一通过synchronized获得锁,并且拿到这个锁10s,然后启动线程二启动去等待获得被线程一拿到的锁,在这期间执行线程二的打断方法,检验打断线程是否会影响锁竞争?
输出结果如下:
结论:
在多线程进行锁竞争的过程中是不会被interrupt所干扰掉的,interrupt本质上就是设置标志位是不会干扰线程的。
interrupt是否能干扰lock呢?
用如下代码做实验:
public class T10_Interrupt_and_lock {
private static ReentrantLock lock = new ReentrantLock();
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
lock.lock();
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
System.out.println("t1 end!");
});
t1.start();
SleepHelper.sleepSeconds(1);
Thread t2 = new Thread(() -> {
lock.lock();
try {
} finally {
lock.unlock();
}
System.out.println("t2 end!");
});
t2.start();
SleepHelper.sleepSeconds(1);
t2.interrupt();
}
}
输出结果如下:
结论:
intterrupt方法干扰不到lock。
那么如何做到真正的打断正在竞争的线程呢?(使用 ReentrantLock 的 lockinterruptibly方法)
public class Interrupt_and_lockInterruptibly {
private static ReentrantLock lock = new ReentrantLock();
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
lock.lock();
try {
SleepHelper.sleepSeconds(10);
} finally {
lock.unlock();
}
System.out.println("t1 end!");
});
t1.start();
SleepHelper.sleepSeconds(1);
Thread t2 = new Thread(() -> {
System.out.println("t2 start!");
try {
lock.lockInterruptibly();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
System.out.println("t2 end!");
});
t2.start();
SleepHelper.sleepSeconds(1);
t2.interrupt();
}
}
说明:在线程二启动的过程中调用 **lock.lockInterruptibly();**将线程二设置为可被打断的状态。
执行结果如下:
当执行t2的interrupt方法时,抛出InterruptedException.