如何使从外部进程捕获输出线程安全?



我编写了一个小方法来执行git命令行工具并捕获其输出:

def git(String command) {
command = "git ${command}"
def outputStream = new StringBuilder()
def errorStream = new StringBuilder()
def process = command.execute()
process.waitForProcessOutput(outputStream, errorStream)
return [process.exitValue(), outputStream, errorStream, command]
}

我正在将其与GPars一起使用以同时克隆多个存储库,例如

GParsPool.withPool(10) {
repos.eachParallel { cloneUrl, cloneDir->
(exit, out, err, cmd) = git("clone ${cloneUrl} ${cloneDir}")
if (exit != 0) {
println "Error: ${cmd} failed with '${errorStream}'."
}
}
}

但是,我相信我的git方法不是线程安全的:例如,第二个线程可以在第一个线程到达方法的第五行command.execute()之前修改方法第一行中的command

我可以通过使整个git方法synchronized来解决这个问题,但这会破坏在不同线程中运行它的目的,因为我希望克隆并行发生。

所以我在想像

def git(String command) {
def outputStream
def errorStream
def process
synchronized {
command = "git ${command}"
outputStream = new StringBuilder()
errorStream = new StringBuilder()
process = command.execute()
}
process.waitForProcessOutput(outputStream, errorStream)
return [process.exitValue(), outputStream, errorStream, command]
}

但我想这也不安全,因为在线程 2 中waitForProcessOutput()可能会比线程 1 更早返回,从而搞砸outputStream/errorStream变量。

获得此线程安全的正确方法是什么?

更改eachParallel闭包参数中的赋值语句,如下所示:

def (exit, out, err, cmd) = git("clone ${cloneUrl} ${cloneDir}")

这将使变量成为闭包的本地变量,进而使它们成为线程安全的变量。git()方法很好。

最新更新