在后台运行JavaExec任务,然后在构建完成时终止



我想弄清楚如何启动一个JavaExec任务,该任务生成一个Jetty服务器,而不会阻塞后续任务。此外,我需要在构建完成后终止此服务器。知道我该怎么做吗?

我知道线程是从2011年开始的,但我仍然偶然发现了这个问题。下面是一个使用Gradle 2.14的解决方案:

import java.util.concurrent.Callable
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors    
class RunAsyncTask extends DefaultTask {
    String taskToExecute = '<YourTask>'
    @TaskAction
    def startAsync() {
        ExecutorService es = Executors.newSingleThreadExecutor()
        es.submit({taskToExecute.execute()} as Callable)
    }
}

task runRegistry(type: RunAsyncTask, dependsOn: build){
    taskToExecute = '<NameOfYourTaskHere>'
}

我更新了@chrishuen的解决方案,因为你不能再调用execute on task了。这是我的工作build.gradle

import java.time.LocalDateTime
import java.util.concurrent.Callable
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
group 'sk.bsmk'
version '1.0-SNAPSHOT'
apply plugin: 'java'
task wrapper(type: Wrapper) {
  gradleVersion = '3.4'
}
class RunAsyncTask extends DefaultTask {
  @TaskAction
  def startAsync() {
    ExecutorService es = Executors.newSingleThreadExecutor()
    es.submit({
      project.javaexec {
        classpath = project.sourceSets.main.runtimeClasspath
        main = "Main"
      }
    } as Callable)
  }
}
task helloAsync(type: RunAsyncTask, dependsOn: compileJava) {
  doLast {
    println LocalDateTime.now().toString() + 'sleeping'
    sleep(2 * 1000)
  }
}

希望这段代码片段能让您对如何做到这一点有所了解。

您可以使用构建监听器闭包在构建开始/结束时运行代码。然而,由于某种原因,gradle.buildStarted闭包不能在里程碑-3中工作,所以我用gradle.taskGraph.whenReady代替了它。

然后您可以使用Task#execute()调用runJetty任务(注意,这个API不是官方的,可能会消失),此外,从ExecutorService运行它以获得一些异步行为。

import java.util.concurrent.*
task myTask << {
  println "Do usual tasks here"
}
task runJetty << {
  print "Pretend we are running Jetty ..."
  while(!stopJetty){
    Thread.sleep(100)
  }
  println "Jetty Stopped."
}
stopJetty = false
es = Executors.newSingleThreadExecutor()
jettyFuture = null
//gradle.buildStarted { ... }
gradle.taskGraph.whenReady { g ->
  jettyFuture = es.submit({ runJetty.execute() } as Callable)
}
gradle.buildFinished {
  println "Stopping Jetty ... "
  stopJetty = true
  //This is optional. Could be useful when debugging.
  try{
    jettyFuture?.get()
  }catch(ExecutionException e){
    println "Error during Jetty execution: "
    e.printStackTrace()
  }
}

JavaExec不行;你得自己写任务

根据之前的回答,以下是我的看法:

abstract class RunAsyncTask extends DefaultTask {
    @Input
    abstract Property<FileCollection> getClasspath()
    @Input
    abstract Property<String> getMain()
    @Input
    abstract ListProperty<String> getArgs()
    @TaskAction
    def startAsync() {
        // do get all the parameters before going asynch, otherwise it sometimes blocks
        def cp = classpath.get().asPath
        def m = main.get()
        def a = args.get()
        ExecutorService es = Executors.newSingleThreadExecutor()
        es.submit({
            def command = ["java", "-cp", cp, m] + a
            ProcessBuilder builder = new ProcessBuilder(command.toList())
            builder.redirectErrorStream(true)
            builder.directory(project.projectDir)
            Process process = builder.start()
            InputStream stdout = process.getInputStream()
            BufferedReader reader = new BufferedReader(new InputStreamReader(stdout))
            def line
            while ((line = reader.readLine()) != null) {
                println line
            }
        } as Callable)
    }
}

task startServer(type: RunAsyncTask) {
    classpath = ...
    main = '...'
    args = [...]
    doLast {
        // sleep 3 seconds to give the server time to startup
        Thread.sleep(3000)
    }
}

最新更新