如何同时运行Gradle多模块项目的两个子项目任务?
如何在Gradle Monorepo中并行运行独立的开发服务器任务
你的Monorepo结构如下:
monorepo build.gradle /api build.gradle /webapp build.gradle
你希望并行运行:api:bootRun和:webapp:runDev这两个无前置依赖(在bootJar执行前无关联)的开发任务,此前用GPars尝试失败,以下是问题分析和可行解决方案:
你的GPars代码问题
你当前的代码存在一个关键错误:在svc.submit中传入的是整个tasksToRun数组,而非当前迭代的单个taskToRun,导致每次调用runDevTaskFromProject都会重复处理全部任务,这是无法正确并行的核心原因。
修复后的GPars代码如下:
tasks.register("dev") { def tasksToRun = ['api:bootRun', 'webapp:runDev'] GParsPool.withPool { ExecutorService svc -> tasksToRun.each { taskToRun -> // 传入当前迭代的单个任务,而非整个任务列表 svc.submit({ runDevTaskFromProject(taskToRun) }) } } } def runDevTaskFromProject(String projectTask) { try { String[] components = projectTask.split(':') GradleRunner.create() .withProjectDir(new File(projectDir, components[0])) .withArguments(components[1]) .forwardOutput() .build() } catch (Exception e) { println "Run Failed: ${e.message}" return } }
同时建议用new File(projectDir, components[0])替代字符串拼接,避免跨平台路径分隔符问题。
更优方案:Gradle Workers API(官方推荐)
Workers API是Gradle官方提供的并行任务执行方案,无需依赖第三方库,能更好地集成Gradle的缓存、输入输出跟踪机制,由Gradle统一管理线程池,稳定性更强:
import org.gradle.workers.WorkerExecutor import javax.inject.Inject tasks.register("dev") { def workerExecutor = project.getServices().get(WorkerExecutor.class) def tasksToRun = ['api:bootRun', 'webapp:runDev'] tasksToRun.each { taskToRun -> workerExecutor.submit(RunDevTask.class) { parameters -> parameters.projectTask.set(taskToRun) parameters.rootProjectDir.set(projectDir) } } } abstract class RunDevTask implements Runnable { @Inject abstract WorkerExecutor getWorkerExecutor() @Input final Property<String> projectTask = project.objects.property(String) @InputDirectory final DirectoryProperty rootProjectDir = project.objects.directoryProperty() @Override void run() { try { String[] components = projectTask.get().split(':') GradleRunner.create() .withProjectDir(rootProjectDir.file(components[0]).get().asFile) .withArguments(components[1]) .forwardOutput() .build() } catch (Exception e) { println "Run Failed: ${e.message}" } } }
关于原生并行参数的说明
你可能会考虑用--parallel参数配合dependsOn实现,但需要注意::api:bootRun和:webapp:runDev都是持续运行的开发服务器任务,Gradle默认会等待任务执行完成才会启动下一个,而开发服务器不会自动退出,因此这种方式无法实现真正的并行运行,还是需要通过独立进程(GradleRunner)或Workers API的方式处理。
内容的提问来源于stack exchange,提问作者bear
相关产品推荐
相关产品推荐

