Java中关于如何实现多线程消息队列的实例(java多线程通信)

Java中关于如何实现多线程消息队列的实例(java多线程通信),第1张

最近遇到一个需求,定时任务的业务逻辑不会改变,但需要动态添加、移除定时任务,而且定时执行时间有可能随时改变,这可怎么实现呢?

首先,配置定时任务线程池;

第二步,建立任务,里面包含了定时任务需要实现的业务逻辑;

第三步,应用定时任务,包括添加、移除;

最后,运行入口程序,打开浏览器进行测试; 通过浏览器分别执行了localhost:8080/index/insert/1000/10、localhost:8080/index/insert/2000/20,也就是添加了两个任务,任务1000每10s执行一次,任务2000每20s执行一次;

执行 >

1、遇到的场景

提高一下插入表的性能优化,两张表,先插旧的表,紧接着插新的表,若是一万多条数据就有点慢了

2、使用步骤

用Spring提供的对 ThreadPoolExecutor 封装的线程池 ThreadPoolTaskExecutor ,直接使用注解启用

配置

@Configuration

@EnableAsync

public class ExecutorConfig {

}

@Value 取值配置是在 applicationproperties 中的

asyncexecutorthreadcore_pool_size = 5

asyncexecutorthreadmax_pool_size = 5

asyncexecutorthreadqueue_capacity = 99999

asyncexecutorthreadnameprefix = async-service-

Demo测试

Service接口

public interface AsyncService {

}

Service实现类

@Service

public class AsyncServiceImpl implements AsyncService {

}

在Controller层注入刚刚的Service即可

@Autowired

private AsyncService asyncService;

@GetMapping("/async")

public void async(){

asyncServiceexecuteAsync();

}

使用测试工具测试即可看到相应的打印结果

3、摸索一下

- 弄清楚线程池当时的情况,有多少线程在执行,多少在队列中等待?

创建一个 ThreadPoolTaskExecutor 的子类,在每次提交线程的时候都将当前线程池的运行状况打印出来

import orgslf4jLogger;

import orgslf4jLoggerFactory;

import orgspringframeworkschedulingconcurrentThreadPoolTaskExecutor;

import orgspringframeworkutilconcurrentListenableFuture;

import javautilconcurrentCallable;

import javautilconcurrentFuture;

import javautilconcurrentThreadPoolExecutor;

public class VisiableThreadPoolTaskExecutor extends ThreadPoolTaskExecutor {

}

进过测试发现: showThreadPoolInfo 方法中将任务总数、已完成数、活跃线程数,队列大小都打印出来了,然后Override了父类的execute、submit等方法,在里面调用showThreadPoolInfo方法,这样每次有任务被提交到线程池的时候,都会将当前线程池的基本情况打印到日志中

现在修改 ExecutorConfigjava 的 asyncServiceExecutor 方法,将 ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor() 改为 ThreadPoolTaskExecutor executor = new VisiableThreadPoolTaskExecutor()

@Bean(name = "asyncServiceExecutor")

public Executor asyncServiceExecutor() {

loggerinfo("start asyncServiceExecutor");

// 在这里进行修改

ThreadPoolTaskExecutor executor = new VisiableThreadPoolTaskExecutor();

// 配置核心线程数

executorsetCorePoolSize(corePoolSize);

// 配置最大线程数

executorsetMaxPoolSize(maxPoolSize);

// 配置队列大小

executorsetQueueCapacity(queueCapacity);

// 配置线程池中的线程的名称前缀

executorsetThreadNamePrefix(namePrefix);

经最后测试得到的结果:提交任务到线程池的时候,调用的是 submit(Callable task) 这个方法,当前已经提交了3个任务,完成了3个,当前有0个线程在处理任务,还剩0个任务在队列中等待

线程池是一种线程使用模式。线程过多会带来额外的开销,其中包括创建销毁线程的开销、调度线程的开销等等,同时也降低了计算机的整体性能。线程池维护多个线程,等待监督管理者分配可并发执行的任务。这种做法,一方面避免了处理任务时创建销毁线程开销的代价,另一方面避免了线程数量膨胀导致的过分调度问题,保证了对内核的充分利用。

使用线程池,有几点好处:

Java开发,我们使用JDK环境,开发框架基本都是Spring全家桶。线程池的基础原理都在JDK中,JDK15新增线程池相关类,在核心jar包 rtjar 中, javautilconcurrent 下面。

看一下jdk中线程池继承关系类图:

JDK中,使用 ThreadPoolExecutor 给创建了几个不同功能种类的线程池,可以调出来看看:

看一下都有什么特点:

从上面可以看出他们各有各的特点,但是阿里巴巴开发守则却不推荐使用以上线程池,因为它们可能会对服务资源的浪费,所以推荐使用通过ThreadPoolExecutor自定线程池。

Spring中将Java中的线程池进行了封装,而且提供了默认实现,也能自定义线程池,我一般都用Spring中的线程池包。

Spring中的线程池和JDK中的基本一样,在 orgspringframeworkschedulingconcurrent 包下面。

和JDK中对应的,Spring的顶层接口是 TaskExecutor ,它实现了JDK中的 Executor 接口。

Spring中常用的线程池是 ThreadPoolTaskExecutor ,它是是借助于JDK并发包中的 javautilconcurrentThreadPoolExecutor 来实现的。

要想使用线程池,先了解一下线程池中的一些参数:

因为我们常用的是 ThreadPoolExecutor 线程池,所以去这个类中找。

上面配置了线程池,并生成了线程池bean,交给了Spring容器管理,使用时注入即可使用。

SpringBoot线程池自动装配在 spring-boot-autoconfigure 这个jar中,在 orgspringframeworkbootautoconfiguretaskTaskExecutionAutoConfiguration 类中。

自动装配条件:

当往线程池中提交新任务时,线程池主要流程如下:

核心线程数 -> 线程队列 -> 最大线程数 -> 拒绝策略

所以使用线程池,需要注意:

以上就是关于Java中关于如何实现多线程消息队列的实例(java多线程通信)全部的内容,包括:Java中关于如何实现多线程消息队列的实例(java多线程通信)、线程池工作原理、合理使用线程池以及线程变量等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/web/10156861.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-05-05
下一篇2023-05-05

发表评论

登录后才能评论

评论列表(0条)

    保存