You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Quarkus微服务中用虚拟线程执行非定时触发的Quartz IO密集型任务

在Quarkus中结合Quartz使用虚拟线程执行程序化触发的IO密集型任务

针对你提到的场景,有两种可行的实现方案,无需依赖Quarkus的@Scheduled注解,即可让IO密集型任务运行在虚拟线程上:

方案一:自定义Quartz线程池适配虚拟线程

Quartz允许通过实现org.quartz.spi.ThreadPool接口自定义线程池,我们可以基于虚拟线程实现该接口,让Quartz直接用虚拟线程执行所有Job。

实现步骤

  1. 编写自定义线程池类:
import org.quartz.spi.ThreadPool;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class VirtualThreadQuartzThreadPool implements ThreadPool {
    private ExecutorService virtualExecutor;

    @Override
    public void initialize() {
        // 创建虚拟线程执行器
        virtualExecutor = Executors.newVirtualThreadPerTaskExecutor();
    }

    @Override
    public void execute(Runnable runnable) {
        virtualExecutor.submit(runnable);
    }

    @Override
    public int getPoolSize() {
        // 虚拟线程池无需固定大小,返回0或自定义逻辑
        return 0;
    }

    @Override
    public boolean runInThread(Runnable runnable) {
        execute(runnable);
        return true;
    }

    @Override
    public void shutdown(boolean waitForJobsToComplete) {
        virtualExecutor.shutdown();
        if (waitForJobsToComplete) {
            try {
                virtualExecutor.awaitTermination(Long.MAX_VALUE, java.util.concurrent.TimeUnit.NANOSECONDS);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    }
}
  1. 在Quarkus配置文件中指定自定义线程池:
# 指定自定义线程池类全路径
org.quartz.threadPool.class=com.yourpackage.VirtualThreadQuartzThreadPool
# 其他Quartz基础配置保持不变
org.quartz.scheduler.instanceName=QuarkusScheduler
org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX

方案二:在Quartz Job内部使用虚拟线程执行核心逻辑

如果不想修改Quartz底层线程池,可以在Job的execute方法中,仅将IO密集的核心逻辑提交到虚拟线程执行器,Quartz的线程池仍使用普通线程(仅负责触发任务,不执行IO操作)。这种方式更轻量,适合快速落地。

实现示例

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class HttpBatchJob implements Job {
    // 复用虚拟线程执行器,避免频繁创建销毁
    private static final ExecutorService VIRTUAL_EXECUTOR = Executors.newVirtualThreadPerTaskExecutor();

    @Override
    public void execute(JobExecutionContext context) {
        // 将批量HTTP请求任务提交到虚拟线程执行
        VIRTUAL_EXECUTOR.submit(() -> {
            // 执行IO密集的HTTP请求逻辑
            for (int i = 0; i < 1000; i++) {
                // 示例:发起HTTP请求
                // HttpClient.newHttpClient().send(
                //     HttpRequest.newBuilder(URI.create("https://example.com")).GET().build(),
                //     HttpResponse.BodyHandlers.ofString()
                // );
            }
        });
    }
}

程序化触发任务的方式

无论采用哪种方案,程序化触发任务都直接调用Quartz的Scheduler API:

import jakarta.enterprise.context.ApplicationScoped;
import org.quartz.Scheduler;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import jakarta.inject.Inject;

@ApplicationScoped
public class JobTriggerService {
    @Inject
    Scheduler scheduler;

    public void triggerHttpBatchJob() throws Exception {
        JobDetail jobDetail = JobBuilder.newJob(HttpBatchJob.class)
                .withIdentity("httpBatchJob", "httpGroup")
                .build();

        scheduler.triggerJob(jobDetail);
    }
}

关键注意事项

  • 确保Quarkus版本支持虚拟线程:建议使用Quarkus 2.13及以上版本,无需额外配置即可使用JDK虚拟线程。
  • 虚拟线程适配场景:你的批量HTTP请求属于典型IO密集场景,完全适配虚拟线程优势;避免在虚拟线程中执行CPU密集型操作。
  • 资源复用:方案二中的虚拟线程执行器建议全局复用,避免频繁创建销毁带来的性能损耗。

内容的提问来源于stack exchange,提问作者LAP

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 23:28:23