一、ThreadInterrupt简介
Java中的Interrupt机制允许线程请求终止另一个线程的执行。ThreadInterrupt()方法通常用于中断阻塞的线程、循环等待的线程或执行复杂运算需要花费大量时间的线程。
实际上,ThreadInterrupt方法并不能直接停止一个线程,而是一种协作机制。具体地说,当一个线程被调用ThreadInterrupt后,线程知道它已被中断,可以在合适的时候自行停止。这个机制需要线程自己去检测是否被中断,如果被中断,则做出对应的处理动作。
二、ThreadInterrupt方法相关方法
Java中提供了几个方法用于线程中断相关操作:
1、isInterrupted()
isInterrupted()方法返回boolean值,用于判断当前线程是否已被中断,不会改变线程中断状态。
public boolean isInterrupted()
2、interrupt()
interrupt()方法用于中断线程,将线程中断状态设为true。如果线程处于一些方法的阻塞状态(如sleep()、wait()、join()等),则会抛出InterruptedException异常,同时会将线程的中断状态复位为false。
public void interrupt()
3、Thread.interrupted()
Thread.interrupted()方法用于返回当前线程的中断状态,并将中断状态设置为false。
public static boolean interrupted()
三、如何使用ThreadInterrupt方法
1、基本用法
以下是一个简单的示例,展示了如何使用ThreadInterrupt方法来中断线程:
public class InterruptDemo{
public static void main(String[] args) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
try {
while (true) {
System.out.println("Thread is running...");
Thread.sleep(1000);
}
} catch (InterruptedException e) {
System.out.println("Thread is interrupted!");
}
}
});
thread.start();
try {
Thread.sleep(5000); // 主线程等待5秒后,中断子线程
} catch (InterruptedException e) {
e.printStackTrace();
}
thread.interrupt(); // 中断子线程
}
}
在该示例中,我们创建了一个线程并启动,该线程每秒钟输出一次信息。在主线程中等待5秒后,使用ThreadInterrupt方法中断子线程。当线程处于等待状态,如Thread.sleep()或Object.wait()等,如果线程中断,那么就会抛出InterruptedException异常。
2、如何让线程中断后退出
当线程在执行任务时被中断,我们往往需要让线程中断后能够安全退出,为此,我们需要让线程在检测到中断状态后自动退出,以下是一个示例:
public class SafeExitDemo {
public static void main(String[] args) {
Thread thread =new Thread(new Runnable() {
@Override
public void run() {
while (!Thread.currentThread().isInterrupted()) {
try {
System.out.println("Thread is running....");
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println("Thread is interrupted!");
Thread.currentThread().interrupt();
}
}
}
});
thread.start();
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
thread.interrupt();
System.out.println("Main thread is finished!");
}
}
在该示例中,当线程捕捉到InterruptedException异常时,我们使用Thread.currentThread().interrupt()手动将线程的中断状态设置为true,以便能够让线程安全退出。
3、如何在队列(blockingQueue)中使用ThreadInterrupt方法
在使用阻塞队列时,我们可能会遇到队列已满或空的情况下,线程就会被阻塞。为了能够让线程在阻塞状态下被中断并终止,我们可以使用ThreadInterrupt方法和ReentrantLock来实现:
public class BlockingQueueInterruptDemo {
private static final int CAPACITY = 5;
private static final ArrayBlockingQueue queue = new ArrayBlockingQueue(CAPACITY);
private static final ReentrantLock lock = new ReentrantLock();
public static void main(String[] args) {
Thread producer = new Thread(new Producer());
Thread consumer = new Thread(new Consumer());
producer.start();
consumer.start();
try {
Thread.sleep(5000); // 主线程等待5秒后,中断子线程
} catch (InterruptedException e) {
e.printStackTrace();
}
producer.interrupt(); // 中断生产者线程
consumer.interrupt(); // 中断消费者线程
}
static class Producer implements Runnable {
@Override
public void run() {
int i = 0;
while (!Thread.currentThread().isInterrupted()) {
lock.lock();
try {
if (queue.size() == CAPACITY) {
System.out.println("Queue is full, producer is waiting, size: " + queue.size());
queue.wait();
} else {
queue.add(++i);
System.out.println("Producer produce data: " + i + ", size: " + queue.size());
Thread.sleep(1000);
queue.notifyAll();
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
lock.unlock();
}
}
}
}
static class Consumer implements Runnable {
@Override
public void run() {
while (!Thread.currentThread().isInterrupted()) {
lock.lock();
try {
if (queue.isEmpty()) {
System.out.println("Queue is empty, consumer is waiting, size: " + queue.size());
queue.wait();
} else {
Integer data = queue.poll();
System.out.println("Consumer consume data: " + data + ", size: " + queue.size());
Thread.sleep(1000);
queue.notifyAll();
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
lock.unlock();
}
}
}
}
}
在该示例中,我们设置了数组阻塞队列的容量为5,如果生产者线程要向队列中添加数据时遇到队列已满阻塞的情况,则会进入等待状态,并释放锁。当队列中有空位置时,则通知所有等待的线程,并重新获得锁进行生产。
同样地,如果消费者线程在队列为空的情况下遇到阻塞,则会进入等待状态。当队列中有数据时,消费者线程会取出数据进行消费,并通知所有等待的线程,并重新获得锁进行消费。
在主线程中等待5秒后,中断生产者线程和消费者线程,线程中断状态为true,则线程会自行停止。
四、ThreadInterrupt方法的注意事项
在使用ThreadInterrupt方法时,需要注意以下事项:
1、ThreadInterrupt方法不能中断正在运行的线程。
一旦线程开始执行,调用ThreadInterrupt方法将不能中断它。只有当它进入到一些会导致阻塞的状态时,才能进行中断。
2、ThreadInterrupt方法会影响线程上下文
当线程被中断时,有些线程不会立即停止,可能会在一个最佳停止时间(安全点)停止。此时,线程的上下文状态就很重要了。线程上下文指的是线程执行一个代码片段时它所在的程序的状态,包括线程的寄存器、堆栈、内存等状态。
3、ThreadInterrupt方法不能保证立即停止线程
中断操作只是在请求中断时,将线程的中断标志位设置为true。线程需要自行检查自己的中断标志位,以决定是否可以安全退出。
五、总结
ThreadInterrupt方法是Java中实现线程中断的一种机制。它允许一个线程中断另一个线程的执行,并在一定程度上使线程停止执行。Java中的ThreadInterrupt方法提供了isInterrupted()、interrupt()和Thread.interrupted()三个方法用于线程的中断状态检查、中断状态设置和中断状态获取。
在使用ThreadInterrupt方法时需要注意,它不能中断正在执行的线程,而是通过请求中断标志来协同线程完成中断的动作。线程需要自行判断中断标志位,只有在合适的时候自行停止执行,才能达到预期的效果。
原创文章,作者:小蓝,如若转载,请注明出处:https://www.506064.com/n/157394.html