interrupt相关的三个方法:
public void interrupt() //t.interrupt() 打断t线程(设置t线程某给标志位f=true,并不是打断线程的运行)
public boolean isInterrupted() //t.isInterrupted() 查询打断标志位是否被设置(是不是曾经被打断过)
public static boolean interrupted()//Thread.interrupted() 查看“当前”线程是否被打断,如果被打断,恢复标志位
1. interrupt() :实例方法,设置线程中断标志(打扰一下,你该处理一下中断)
2. isInterrupted():实例方法,有没有人打扰我?
3. interrupted():静态方法,有没有人打扰我(当前线程)?复位!
interrupt和sleep() wait() join()
sleep()方法在睡眠的时候,不到时间是没有办法叫醒的,这个时候可以用interrupt设置标志位,然后呢必须得catch InterruptedException来进行处理,决定继续睡或者是别的逻辑,(自动进行中断标志复位)
interrupt是否能中断正在竞争锁的线程
public class SleepHelper {
public static void sleepSeconds(int seconds){
try {
Thread.sleep(seconds*1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class T09_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();
t2.interrupt();
}
}
//输出: t2 end!
结论:interrupt()不能打断正在竞争锁的线程synchronized()
如果想打断正在竞争锁的线程,使用ReentrantLock的lockInterruptibly()
import java.util.concurrent.locks.ReentrantLock;
public class T11_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();
}
}
输出结果
t2 start!
java.lang.InterruptedException
at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireInterruptibly(AbstractQueuedSynchronizer.java:898)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireInterruptibly(AbstractQueuedSynchronizer.java:1222)
at java.util.concurrent.locks.ReentrantLock.lockInterruptibly(ReentrantLock.java:335)
at com.example.demo.test.T11_Interrupt_and_lockInterruptibly.lambda$main$1(T11_Interrupt_and_lockInterruptibly.java:28)
at java.lang.Thread.run(Thread.java:748)
Exception in thread "Thread-1" java.lang.IllegalMonitorStateException
at java.util.concurrent.locks.ReentrantLock$Sync.tryRelease(ReentrantLock.java:151)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.release(AbstractQueuedSynchronizer.java:1261)
at java.util.concurrent.locks.ReentrantLock.unlock(ReentrantLock.java:457)
at com.example.demo.test.T11_Interrupt_and_lockInterruptibly.lambda$main$1(T11_Interrupt_and_lockInterruptibly.java:32)
at java.lang.Thread.run(Thread.java:748)
t1 end!
优雅的结束线程
1. 自然结束(能自然结束就尽量自然结束)
2. stop() suspend() resume()
3. volatile标志
1. 不适合某些场景(比如还没有同步的时候,线程做了阻塞操作,没有办法循环回去)
2. 打断时间也不是特别精确,比如一个阻塞容器,容量为5的时候结束生产者,
但是,由于volatile同步线程标志位的时间控制不是很精确,有可能生产者还继续生产一段儿时间
4. interrupt() and isInterrupted(比较优雅)