java线程手动销毁_java中如何终止线程的执行

本文介绍了在Java中如何手动销毁线程,包括设置退出标志和调用线程的`interrupt()`方法。当线程在无限循环中执行任务时,可以设置一个volatile布尔变量作为退出标志,当该标志为false时结束循环。此外,通过调用线程的`interrupt()`方法,可以设置线程的中断标识,但需注意在阻塞状态下中断会抛出`InterruptedException`,需要配合退出标志共同使用以避免线程无法终止的情况。
部署运行你感兴趣的模型镜像

java中如何终止线程的执行

线程被创建后,当run()方法执行完毕,线程便会正常结束和销毁。但是,在有些情况下,run() 方法是永远不会执行完的,比如在run()方法中进行while()轮询任务时,这种情况下就需要我们通过代码手动的退出线程。

这里我们介绍以下几种方法:

1. 使用退出标识

添加一个boolean类型的变量isRun作为线程的退出标识,当isRun为false时,结束循环以中断线程。

public class CloseThread {

public static class CreateThread extends Thread {

//定义退出标志,true一直执行,false退出循环

public volatile boolean isRun = true;

@Override

public void run() {

System.out.println("创建线程完成");

while (isRun) {

System.out.println("工作中..., thread name =" + Thread.currentThread().getName());

SleepUtils.second(1);//线程停止1秒

}

System.out.println("创建执行完毕");

}

public void interrupt() {

System.out.println("中断标识设置为false");

this.isRun = false;

}

}

public static void main(String[] args) {

//实例化一个线程并 start()

Thread thread = new CreateThread();

thread.start();

//线程停止5秒

SleepUtils.second(5);

System.out.println("尝试中断线程");

thread.interrupt();

}

}

执行代码,打印以下结果:

创建线程完成

工作中..., thread name =Thread-0

工作中..., thread name =Thread-0

工作中..., thread name =Thread-0

工作中..., thread name =Thread-0

工作中..., thread name =Thread-0

开始尝试中断线程

中断标识设置为false

线程执行完成

在main()中调用interrupt(),设置线程的中断标识为false,最终成功结束了循环中断了线程的执行。

2. 调用线程本身的interrupt()方法

interrupt()方法是线程本身的一种中断标识,通过调用这个方法可以将线程的isInterrupted()设置为true。

public class CloseThread2 {

public static class CreateThread2 extends Thread {

@Override

public void run() {

while (!currentThread().isInterrupted()) {

System.out.println("工作中...");

}

System.out.println("线程执行完成");

}

}

public static void main(String[] args) {

//实例化一个线程并start()

CreateThread2 thread = new CreateThread2();

thread.start();

//当前线程停止1s

SleepUtils.second(1);

//调用线程的interrupt()

thread.interrupt();

System.out.println("中断线程,thread " + thread.getId() + " :" + thread.isInterrupted());

}

}

执行代码,打印以下结果:

工作中...

工作中...

工作中...

工作中...

工作中...

工作中...

工作中...

工作中...

工作中...

工作中...

中断线程,thread 11 :true

线程执行完成

在main()中调用线程本身的interrupt(),设置线程的中断标识isInterrupted()为true,最终成功结束了循环中断了线程的执行。

但是使用interrupt()时需要注意线程是否处于阻塞状态。当对处于阻塞状态的线程调用interrupt()方法时,会抛出InterruptException异常,而这个异常会清除中断标识,也就是会将中断标识重新修改为false。

我们可以通过以下代码来模拟这种情况:

public class CloseThread3 {

public static class CreateThread3 extends Thread {

@Override

public void run() {

System.out.println("thread 已创建" + currentThread().getId() + " :" + currentThread().isInterrupted());

while (!currentThread().isInterrupted()) {

System.out.println("工作中...");

try {

//线程暂停3秒,模拟处于阻塞状态

Thread.sleep(3000);

} catch (InterruptedException e) {

e.printStackTrace();

System.out.println("抛出异常,thread " + currentThread().getId() + " :" + currentThread().isInterrupted());

}

}

System.out.println("线程执行完成");

}

}

public static void main(String[] args) {

CreateThread3 thread = new CreateThread3();

thread.start();

//当前线程暂停5秒

SleepUtils.second(5);

System.out.println("开始尝试中断线程");

//调用线程的interrupt()

thread.interrupt();

System.out.println("中断线程,thread " + thread.getId() + " :" + thread.isInterrupted());

}

}

执行代码,打印以下结果:

thread 已创建11 :false

工作中...

工作中...

开始尝试中断线程

中断线程,thread 11 :false

抛出异常,thread 11 :false

工作中...

java.lang.InterruptedException: sleep interrupted

at java.lang.Thread.sleep(Native Method)

at threadDemo.CloseThread3$CreateThread2.run(CloseThread3.java:15)

工作中...

工作中...

工作中...

.........(不断的打印工作中...)

由此可见,当线程处于阻塞状态中,调用线程的interrupt()将线程的中断标识isInterrupted()设置为,但是当抛出InterruptException异常时,会清除中断标识,将中断标识重新修改为false,导致线程并不会被终止,而是一直执行下去。

为了解决这种情况,我们可以将本文所讲的这两种中断线程的方法组合使用,为线程添加一个中断标识变量,并且重写interrupt()方法:

public class CloseThread4 {

public static class CreateThread4 extends Thread {

//定义退出标志,true会一直执行,false会退出循环

public volatile boolean isRun = true;

@Override

public void run() {

System.out.println("thread 已创建" + currentThread().getId() + " :" + currentThread().isInterrupted());

while (isRun && !currentThread().isInterrupted()) {

System.out.println("工作中...");

try {

//线程暂停3秒,模拟处于阻塞状态

Thread.sleep(3000);

} catch (InterruptedException e) {

e.printStackTrace();

System.out.println("抛出异常,thread " + currentThread().getId() + " :" + currentThread().isInterrupted());

}

}

System.out.println("线程执行完成");

}

/**

* 重写interrupt()

*/

@Override

public void interrupt() {

System.out.println("中断标识isRun设置为false");

this.isRun = false;

super.interrupt();

}

}

public static void main(String[] args) {

CreateThread4 thread = new CreateThread4();

thread.start();

//当前线程暂停5秒

SleepUtils.second(5);

System.out.println("开始尝试中断线程");

//调用线程的interrupt()

thread.interrupt();

System.out.println("中断线程,thread " + thread.getId() + " :" + thread.isInterrupted());

}

}

执行代码,打印以下结果:

thread 已创建11 :false

工作中...

工作中...

java.lang.InterruptedException: sleep interrupted

at java.lang.Thread.sleep(Native Method)

at threadDemo.CloseThread4$CreateThread4.run(CloseThread4.java:17)

开始尝试中断线程

中断标识设置为false

中断线程,thread 11 :true

抛出异常,thread 11 :false

线程执行完成

通过自定义中断标识和线程isInterrupted()中断标识组合使用,便解决了线程处于阻塞中调用interrupt()导致isInterrupted()被清除的问题。

您可能感兴趣的与本文相关的镜像

Yolo-v8.3

Yolo-v8.3

Yolo

YOLO(You Only Look Once)是一种流行的物体检测和图像分割模型,由华盛顿大学的Joseph Redmon 和Ali Farhadi 开发。 YOLO 于2015 年推出,因其高速和高精度而广受欢迎

<think>好的,我现在需要回答用户关于Java核心线程销毁及生命周期行为的问题。首先,用户提到的核心线程应该是指线程池中的核心线程,比如ThreadPoolExecutor中的corePoolSize所指定的那些线程。 根据Java的ThreadPoolExecutor文档,核心线程默认情况下会一直存活,即使它们处于空闲状态。不过,可以通过设置allowCoreThreadTimeOut为true来让核心线程在空闲超时后销毁。这个参数默认是false,所以一般情况下核心线程不会被回收。用户可能需要知道默认行为和如何修改配置。 另外,用户提到的ThreadPoolTaskExecutor是Spring对ThreadPoolExecutor的封装,所以行为应该是一致的。参考引用[1]中的内容,ThreadPoolTaskExecutor包装了java.util.concurrent.ThreadPoolExecutor,并允许配置相关属性。所以这里需要指出Spring中的线程池配置和原生Java的区别或相似之处。 关于生命周期,引用[2]提到了Spring的SmartLifecycle接口,用于管理组件的启动和停止。虽然线程池的生命周期可能与之相关,但核心线程销毁更多是线程池自身的配置,而不是直接由Spring的生命周期接口控制。不过,可能需要提到在Spring应用中如何配置线程池的参数,比如通过属性设置corePoolSize和allowCoreThreadTimeOut。 用户的问题还涉及到线程的生命周期行为。线程池中的线程在完成任务后,会从队列中获取下一个任务。如果没有任务且允许核心线程超时,或者线程数超过corePoolSize,非核心线程会被回收。需要详细说明不同情况下的线程回收机制。 可能需要注意Java版本的影响,是否有不同版本中的行为差异,但用户没有特别指出版本,所以假设是普遍情况。另外,需要提到如何配置线程池参数来控制核心线程销毁,例如使用allowCoreThreadTimeOut方法。 总结回答的结构应该是: 1. 核心线程默认不销毁,除非配置allowCoreThreadTimeOut为true。 2. 生命周期由线程池管理,任务执行后等待新任务,超时或配置改变时销毁。 3. 在Spring中通过ThreadPoolTaskExecutor配置相关属性。 4. 对比核心线程和非核心线程的不同行为。 然后生成相关问题,考虑线程池配置、Spring中的线程池管理、如何处理线程池资源等。</think>在Java线程池中,核心线程的生命周期行为由以下机制控制: ### 一、核心线程销毁规则 1. **默认行为** 核心线程(corePoolSize)默认永久存活,即使处于空闲状态也不会销毁。这是通过线程池的$allowCoreThreadTimeOut$参数控制的,该参数默认值为$false$[^1] 2. **主动销毁条件** 若设置$allowCoreThreadTimeOut=true$,核心线程在空闲超时后会被销毁。超时时间由$keepAliveTime$参数定义,与普通线程(超出corePoolSize的线程)共享相同的超时配置 $$ \text{线程存活条件} = \begin{cases} \text{永久存活} & \text{if } allowCoreThreadTimeOut=false \\ \text{超时销毁} & \text{if } allowCoreThreadTimeOut=true \end{cases} $$ ### 二、生命周期流程 1. **初始化阶段** - 线程池创建时不会预初始化核心线程 - 首个任务提交时才会创建核心线程 2. **任务处理阶段** - 核心线程从工作队列中通过$workQueue.take()$阻塞获取任务 - 当$allowCoreThreadTimeOut=true$时,改用$workQueue.poll(keepAliveTime, TimeUnit)$ 3. **终止阶段** - 调用$shutdown()$后,所有线程(包括核心线程)会处理完队列中的剩余任务后终止 - 调用$shutdownNow()$会立即中断所有线程 ### 三、Spring中的配置示例 通过ThreadPoolTaskExecutor配置核心线程行为: ```java @Bean public ThreadPoolTaskExecutor taskExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(5); executor.setMaxPoolSize(10); executor.setKeepAliveSeconds(60); executor.setAllowCoreThreadTimeOut(true); // 允许核心线程超时 executor.setQueueCapacity(100); return executor; } ``` 此配置会使核心线程在60秒空闲后销毁[^2] ### 四、特殊场景说明 1. **构造器循环依赖** 虽然与线程池无关,但需注意Spring容器中类似线程池组件的初始化要避免循环依赖问题[^3][^4] 2. **原型作用域线程池** 若线程池被声明为prototype作用域,每次注入都会创建新实例,需要手动管理销毁[^4]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值