线程的打断(interrupt)
interrupt相关的三个方法:
//Thread.java
public void interrupt() //t.interrupt() 打断t线程(设置t线程某给标志位f=true,并不是打断线程的运行)
public boolean isInterrupted() //t.isInterrupted() 查询打断标志位是否被设置(是不是曾经被打断过)
public static boolean interrupted()//Thread.interrupted() 查看“当前”线程是否被打断,如果被打断,恢复标志位
- interrupt() :实例方法,设置线程中断标志(打扰一下,你该处理一下中断)
- isInterrupted():实例方法,有没有人打扰我?
- interrupted():静态方法,有没有人打扰我(当前线程)?复位!
interrupt和sleep() wait() join()
sleep()方法在睡眠的时候,不到时间是没有办法叫醒的,这个时候可以用interrupt设置标志位,然后呢必须得catch InterruptedException来进行处理,决定继续睡或者是别的逻辑,(自动进行中断标志复位)
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();
}
public static void main(String[] args) {
Thread t = new Thread(() -> {
for (; ; ) {
if (Thread.interrupted()) {
System.out.println("Thread is interrupted!");
System.out.println(Thread.interrupted());
}
}
});
t.start();
SleepHelper.sleepSeconds(2);
t.interrupt();
//思考一下,如果在这里写
System.out.println("main: " + t.interrupted());
//输出的是哪个线程的中断状态
}
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();
}
private static Object o = new Object();
public static void main(String[] args) {
Thread t = new Thread(() -> {
synchronized (o) {
try {
o.wait();
} catch (InterruptedException e) {
System.out.println("Thread is interrupted!");
System.out.println(Thread.currentThread().isInterrupted());
}
}
});
t.start();
SleepHelper.sleepSeconds(5);
t.interrupt();
}
interrupt是否能中断正在竞争锁的线程
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();
}
interrupt()不能打断正在竞争锁的线程synchronized()
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();
}
如果想打断正在竞争锁的线程,使用ReentrantLock的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();
}
优雅的结束线程
结束线程的方法:
- 自然结束(能自然结束就尽量自然结束)
- stop() suspend() resume()
- volatile标志
- 不适合某些场景(比如还没有同步的时候,线程做了阻塞操作,没有办法循环回去)
- 打断时间也不是特别精确,比如一个阻塞容器,容量为5的时候结束生产者,
但是,由于volatile同步线程标志位的时间控制不是很精确,有可能生产者还继续生产一段儿时间
- interrupt() and isInterrupted(比较优雅)
public static void main(String[] args) {
Thread t = new Thread(() -> {
while (true) {
System.out.println("go on");
SleepHelper.sleepSeconds(1);
}
});
t.start();
SleepHelper.sleepSeconds(5);
t.stop();
}
public static void main(String[] args) {
Thread t = new Thread(() -> {
while (true) {
System.out.println("go on");
SleepHelper.sleepSeconds(1);
}
});
t.start();
SleepHelper.sleepSeconds(5);
t.suspend();
SleepHelper.sleepSeconds(3);
t.resume();
}
private static volatile boolean running = true;
public static void main(String[] args) {
Thread t = new Thread(() -> {
long i = 0L;
while (running) {
//wait recv accept
i++;
}
System.out.println("end and i = " + i);
});
t.start();
SleepHelper.sleepSeconds(1);
running = false;
}
public static void main(String[] args) {
Thread t = new Thread(() -> {
while (!Thread.interrupted()) {
//sleep wait
}
System.out.println("t1 end!");
});
t.start();
SleepHelper.sleepSeconds(1);
t.interrupt();
}
public static void main(String[] args) {
Thread t = new Thread(() -> {
System.out.println("1");
LockSupport.park();
System.out.println("2");
});
t.start();
SleepHelper.sleepSeconds(1);
t.interrupt();
}