设为首页 加入收藏

TOP

Java线程的中断(一)
2019-09-03 03:40:10 】 浏览:17
Tags:Java 线程 中断

引言


正文


一、中断相关的方法介绍


涉及到中断的线程基础方法有三个:interrupt()、isInterrupted()、interrupted(),它们都位于Thread类下。Thread类下还有一个


interrupt()方法:对目标线程发送中断请求,看其源码会发现最终是调用了一个本地方法实现的线程中断;


interrupted()方法:返回目标线程是否中断的布尔值(通过本地方法实现),且返回后会重置中断状态为未中断;


isInterrupted()方法:该方法返回的是线程中断与否的布尔值(通过本地方法实现),不会重置中断状态;


二、线程中断


线程中断可以按中断时线程状态分为两类,一类是运行时线程的中断,一类是阻塞或等待线程的中断。有中断时,运行时的线程会在某个取消点中断执行,而处于阻塞或者等待状态的线程大多会立即响应中断,比如上一篇文章中提到的join、sleep等方法,这些方法在抛出中断异常的错误后,会重置线程中断状态为未中断。但注意,获取独占锁的阻塞状态与BIO的阻塞状态不会响应中断。而在JUC包中有在加锁阻塞的过程中响应中断的方法,比如lockInterruptibly()。


下面从三个问题来讲述线程中断


1、线程中断的目的是什么?


为什么要进行线程中断?有时是由于对于某种特定情况,我们知道当前线程无需继续执行下去,此时可以中断此线程;有时是遇到某些异常,需要中断线程。具体什么目的,还要看具体场景,但线程中断的需求已经摆在那里,肯定需要。


2、要如何处理线程中断?


通常的处理方式有两种,如果是业务层面的代码,则只需要做好中断线程之后的业务逻辑处理即可,而如果是偏底层功能的线程中断,则尽量将中断异常抛出(或者在catch中重新调用interrupt()来中断线程),以告知上层方法本线程的中断经历。


3、JUC中对中断的处理举例


JUC中ReentrantLock常用的加锁方法是lock(),还有一个响应中断的加锁方法lockInterruptibly()


lock()方法中的acquire(int arg)方法如下所示:


1 public final void acquire(int arg) {
2? ? ? ? if (!tryAcquire(arg) &&
3? ? ? ? ? ? acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
4? ? ? ? ? ? selfInterrupt();
5 }


在acquireQueued中会对线程的中断状态做判断,如果中断了则返回true,进入selfInterrupt()方法,恢复线程的中断状态。但注意此处是在获取到锁之后再响应中断,在获取到锁之前不会做出响应。


1 static void selfInterrupt() {
2? ? ? ? Thread.currentThread().interrupt();
3 }


而看lockInterruptibly()方法:


public void lockInterruptibly() throws InterruptedException {
? ? ? ? sync.acquireInterruptibly(1);
? ? }


public final void acquireInterruptibly(int arg)
? ? ? ? ? ? throws InterruptedException {
? ? ? ? if (Thread.interrupted())
? ? ? ? ? ? throw new InterruptedException();
? ? ? ? if (!tryAcquire(arg))
? ? ? ? ? ? doAcquireInterruptibly(arg);
? ? }


它会先查看中断状态,再获取锁。而如果在获取锁的过程中中断过,则会在doAcquireInterruptibly方法中抛出中断异常。


下面是我在本地模拟的lock阻塞中断:


public class ReentrantLockDemo {
? ? public static void main(String[] args) throws InterruptedException {
? ? ? ? System.out.println("main start");
? ? ? ? Thread thread1 = new Thread(new LockThreadDemo());
? ? ? ? Thread thread2 = new Thread(new LockThreadDemo());
? ? ? ? thread1.start();
? ? ? ? Thread.sleep(1000); // 确保thread1获取到了锁
? ? ? ? thread2.start(); // 此时thread2处于获取锁的阻塞状态
? ? ? ? thread2.interrupt();
? ? ? ? System.out.println("main end");
? ? }
}


class LockThreadDemo implements Runnable {
? ? public static ReentrantLock lock = new ReentrantLock();
? ? @Override
? ? public void run() {
? ? ? ? System.out.println(Thread.currentThread().getName() + "runnable run");
? ? ? ? try {
? ? ? ? ? ? lock.lock();
? ? ? ? ? ? System.out.println(Thread.currentThread().getName() + "开始睡眠");
? ? ? ? ? ? Thread.sleep(5000);
? ? ? ? ? ? System.out.println(Thread.currentThrea
Java线程的中断(一) https://www.cppentry.com/bencandy.php?fid=54&id=249483

首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Thread线程的基础知识及常见疑惑点 下一篇算法之常见排序算法-冒泡排序、归..

kafka-
kafka ? Partit
解决android studio
Kafka史上最详细原理
Error while fetchin
【Kafka】安装与快速
? ? &
flume读取日志数据写
Authentication plug
Flume 自定义source
flume ? 三大核
ICC副本>>>
愚公移山 ?
Hbase架构 ? Hb
5 hbase-shell + &
Hbase ? MapRed
MetaException(messa
Exception in thread
HIVE metastore Dupl
-->