Java 之使用消息队列实现一系列的功能
为了梳理任务的流转过程,我们可以从以下几个关键点进行分析:
- 任务提交:任务通过
BatchController
中的接口方法(如laneinfo
和patch
)被提交。 - 任务排队:提交的任务会被放入
TaskQueue
中。 - 任务处理:
TaskProcessor
中的线程会从TaskQueue
中取出任务并执行。 - 任务执行:任务执行的具体逻辑在
Task
类的run
方法中定义。
流程图#
+-----------------+ +-----------------+ +-----------------+ +-----------------+
| BatchController | | TaskQueue | | TaskProcessor | | Task |
+-----------------+ +-----------------+ +-----------------+ +-----------------+
| | | |
| 1. 提交任务 | | |
|------------------------->| | |
| | 2. 任务入队 | |
| |------------------------->| |
| | | 3. 处理任务 |
| | |<-------------------------|
| | | |
| | | 4. 执行任务 |
| | |------------------------->|
| | | |
| | | 5. 任务完成 |
| | |<-------------------------|
| | | |
| | | 6. 返回结果 |
| | |------------------------->|
| | | |
| | | 7. 任务队列为空 |
| | |<-------------------------|
| | | |
核心逻辑#
-
任务提交:
BatchController
中的laneinfo
和patch
方法接收请求参数,创建Task
对象,并将其放入TaskQueue
中。Task
对象包含执行任务所需的Callable
和CompletableFuture
。
-
任务排队:
TaskQueue
使用BlockingQueue
来存储任务,确保任务的顺序性和线程安全。
-
任务处理:
TaskProcessor
启动多个线程,每个线程从TaskQueue
中取出任务并执行。- 如果线程被中断,会重新设置中断状态并记录日志。
-
任务执行:
Task
的run
方法中,通过Callable
执行具体的业务逻辑,并将结果放入CompletableFuture
中。- 如果执行过程中发生异常,会记录日志并抛出
RuntimeException
。
代码实现#
以下是核心逻辑的代码实现,主要集中在BatchController
、TaskQueue
、TaskProcessor
和Task
类中。
BatchController.java#
CompletableFuture<EntityResponse<?>> future = new CompletableFuture<>();
Task task = Task.builder()
.callable(() -> server.execute(param))
.future(future)
.build();
try {
taskQueue.enqueue(task); // 将任务添加到队列中
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
return future.join();
TaskQueue.java#
@Component
public class TaskQueue {
private final BlockingQueue<Task> queue = new LinkedBlockingQueue<>();
public void enqueue(Task task) throws InterruptedException {
queue.put(task);
}
public Task dequeue() throws InterruptedException {
return queue.take();
}
public int size() {
return queue.size();
}
public void clear() {
queue.clear();
}
public boolean isEmpty() {
return queue.isEmpty();
}
}
TaskProcessor.java#
@Slf4j
@Service
public class TaskProcessor {
@Resource
private TaskQueue taskQueue;
@Resource(name = "commonThreadPool")
private ThreadPoolTaskExecutor threadPoolTaskExecutor;
public void processTasks() {
// 1. 每个线程的线程任务死循环
// 2, 这里触发的是提交任务到线程池中执行
//3. 控制一下,提交多少个任务到线程池中
int consumerThreadCount = 10;
for (int i = 0; i < consumerThreadCount; i++) {
threadPoolTaskExecutor.execute(() -> {
while (!Thread.currentThread().isInterrupted()) {
try {
Task task = taskQueue.dequeue();
task.run();
} catch (InterruptedException e) {
log.error("Thread interrupted", e);
Thread.currentThread().interrupt(); // 重新设置中断状态
} catch (Exception e) {
log.error("Error processing task", e);
}
}
});
}
}
}
Task.java#
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Task {
private AuthInfo authInfo;
private Callable<EntityResponse<?>> callable;
private CompletableFuture<EntityResponse<?>> future;
public void run() {
try {
AuthInfoUtils.fillVirtualAuth();
EntityResponse<?> response = callable.call();
future.complete(response);
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
AuthInfoUtils.clear();
}
}
}
TaskProcessorRunner.java#
@Component
public class TaskProcessorRunner implements CommandLineRunner {
@Resource
private TaskProcessor taskProcessor;
@Override
public void run(String... args) throws Exception {
taskProcessor.processTasks(); // 启动任务处理器
}
}
以上代码展示了任务提交、排队、处理和执行的核心逻辑。通过这些步骤,任务能够被有序地处理,并且在处理过程中能够优雅地响应中断信号。
本文来自博客园,作者:快乐小王子帅气哥哥,转载请注明原文链接:https://www.cnblogs.com/alex-oos/p/18743162
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通