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

发布于 2024-12-11 13:09:31 字数 80 浏览 0 评论 0原文

我试图找出如何启动一个 JavaExec 任务来生成 Jetty 服务器而不阻塞后续任务。另外,我需要在构建完成后终止该服务器。知道我该怎么做吗?

I'm trying to figure out how to launch a JavaExec task that spawns a Jetty server without blocking subsequent tasks. Also, I will need to terminate this server after the build completes. Any idea how I can do this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

甚是思念 2024-12-18 13:09:31

我知道该线程是 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>'
}

I know the thread is from 2011, but I still stumbled across the problem. So here's a solution working with 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>'
}
装迷糊 2024-12-18 13:09:31

我更新了 @chrishuen 的解决方案,因为您无法再对任务调用执行。这是我的工作 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)
  }
}

I updated solution from @chrishuen because you cannot call execute on task anymore. Here is my working 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)
  }
}
紫罗兰の梦幻 2024-12-18 13:09:31

希望这段代码能让您了解如何完成它。

您可以使用构建侦听器闭包在构建开始/结束时运行代码。然而,由于某种原因, gradle.buildStarted 闭包在 Milestone-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()
  }
}

Hope this snippet will give you some insight on how it can be done.

You can used build listener closures to run code on build start/finish. However, for some reason, gradle.buildStarted closure does not work in milestone-3, so I have replaced it with gradle.taskGraph.whenReady which does the trick.

Then you can call the runJetty task using Task#execute() (Note, this API is not official and may disappear), and additionally, run it from an ExecutorService to get some asynchronous behaviour.

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()
  }
}
懷念過去 2024-12-18 13:09:31

你不能用 JavaExec 来做到这一点;你必须编写自己的任务。

You can't do it with JavaExec; you'll have to write your own task.

囚你心 2024-12-18 13:09:31

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

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)
    }
}

Based on previous answers, here is my take:

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)
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文