一、中断线程
1.1、例1:中断运行中的线程
/**
* 打断运行中的线程
*/
@Slf4j
public class SleepRunTest {
public static void main(String[] args) throws InterruptedException {
Thread t1=new Thread(()->{
log.info("线程t1开始运行");
while (true){
if (Thread.currentThread().isInterrupted()){
log.info("运行中的线程被中断,结束,中断标记:{}",Thread.currentThread().isInterrupted());
break;
}
}
},"t1");
t1.start();
Thread.sleep(1000);
log.info("中断线程t1");
/**
* (1) interrupt也可以打断正在运行的线程
* (2) interrupt可以打断sleep、wait、join状态的线程
* (3) 线程被中断后,中断标记为true。但是如果经过异常处理,则中断标记会重置为false
*/
t1.interrupt();
}
}
运行结果
[INFO ] 16:58:19.857 [t1] - 线程t1开始运行
[INFO ] 16:58:20.857 [main] - 中断线程t1
[INFO ] 16:58:20.857 [t1] - 运行中的线程被中断,结束,中断标记:true
1.2、例2:中断等待线程
/**
* 打断睡眠中的线程举例
*/
@Slf4j
public class SleepTest {
public static void main(String[] args) throws InterruptedException {
Thread t1=new Thread(()->{
log.info("开始睡眠");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
//抛出异常时,打断标记会被重置为false,所以经过异常处理后的打断标记为false
log.info("睡眠中断,中断标记:{}",Thread.currentThread().isInterrupted());
e.printStackTrace();
}
},"t1");
t1.start();
Thread.sleep(1000);
log.info("中断线程t1睡眠");
/**
* (1)interrupt可以打断sleep、wait、join、park状态的线程
* (2) interrupt也可以打断正在运行的线程
* (3) 线程被中断后,中断标记为true。但是如果经过异常处理,则中断标记会重置为false
*/
t1.interrupt();
}
}
运行结果:
[INFO ] 17:03:23.898 [t1] - 开始睡眠
[INFO ] 17:03:24.915 [main] - 中断线程t1睡眠
[INFO ] 17:03:24.917 [t1] - 睡眠中断,中断标记:false
java.lang.InterruptedException: sleep interrupted
1.3、例3:使用park实现等待
@Slf4j
public class UnparkTest {
public static void main(String[] args) throws InterruptedException {
Thread t1=new Thread(()->{
try {
log.info("开始等待");
/**
* 调用park()方法返回之后,会将打断标记设置为false
*/
LockSupport.park();
log.info("结束等待,中断标记:{}",Thread.currentThread().isInterrupted());
} catch (Exception e) {
log.info("线程中断,中断标记:{}",Thread.currentThread().isInterrupted());
e.printStackTrace();
}
},"t1");
t1.start();
Thread.sleep(1000);
log.info("中断线程t1");
/**
* (1)interrupt可以打断sleep、wait、join、park状态的线程
* (2) interrupt也可以打断正在运行的线程
*/
LockSupport.unpark(t1);
}
}
运行结果
[INFO ] 17:25:20.060 [t1] - 开始等待
[INFO ] 17:25:21.076 [main] - 中断线程t1
[INFO ] 17:25:21.076 [t1] - 结束等待,中断标记:false
二、线程同步
2.1 举例1:使用join实现线程同步
@Slf4j
public class JionTest {
private static int tmp=0;
public static void main(String[] args) throws InterruptedException {
Thread t1=new Thread(()->{
log.info("开始睡眠");
try {
Thread.sleep(2000);
tmp=10;
} catch (InterruptedException e) {
e.printStackTrace();
}
},"t1");
t1.start();
/**
* 1、线程同步:等待t1运行结束,等待期间t1状态为waiting
* 2、join方法底层,使用wait()实现
*/
t1.join();
log.info("tmp:{}",tmp);
}
}
运行结果
[INFO ] 17:26:21.879 [t1] - 开始睡眠
[INFO ] 17:26:23.899 [main] - tmp:10
三、不可中断锁的理解
/**
* ReentrantLock与synchronized区别
* 1、可中断:synchronized加的锁,不能被中断(注意不是线程中断)
* 2、可以设置超时时间:lock.tryLock(1000)--》获取所时,指定时间内仍没获取到锁,则放弃争抢锁
* 3、尝试非阻塞的获取锁: lock.tryLock()-->尝试获取一次锁
* 4、可以设置公平锁:
* 5、支持多个条件变量
*
* ReentrantLock与synchronized都是可重入锁
*/
@Slf4j
public class ReentraInterruptTest {
private static ReentrantLock lock=new ReentrantLock();
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(() -> {
try {
log.info("t1尝试获得锁");
/**
* 1、使用lock.lockInterruptibly()方法争抢锁时,才能被打断
* 2、使用lock.lock()方法争抢锁时,和synchronized一样也是不能被打断的
* 3、lock.tryLock()方法:尝试非阻塞的获取一次锁
*/
//lock.lock();
lock.lockInterruptibly();
log.info("t1获得锁");
} catch (Exception e) {
//抛出异常时,打断标记会被重置,所以异常中获得的打断标记为false
log.info("t1尝试获取锁被打断,打断标记为:{}",Thread.currentThread().isInterrupted());
e.printStackTrace();
return;
} finally {
lock.unlock();
}
},"t1");
lock.lock();
t1.start();
sleep(3000);
log.info("打断t1争抢锁");
t1.interrupt();
}
}
(1)使用lock.lockInterruptibly();运行结果
[INFO ] 17:35:06.120 [t1] - t1尝试获得锁
[INFO ] 17:35:09.133 [main] - 打断t1争抢锁
[INFO ] 17:35:09.133 [t1] - t1尝试获取锁被打断,打断标记为:false
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)
(2)使用lock.lock();运行结果–》不会被打断
[INFO ] 17:37:03.635 [t1] - t1尝试获得锁
[INFO ] 17:37:06.627 [main] - 打断t1争抢锁