代码之家  ›  专栏  ›  技术社区  ›  Binil Thomas

在Groovy或Java中启动进程并等待条件

  •  1
  • Binil Thomas  · 技术社区  · 15 年前

    这就是我想出来的。有更好的办法吗?

    def proc = "groovy test.groovy".execute(null, new File("."))
    def timeout = 10 * 1000
    
    printProcessOutput(proc, timeout) {line, count -> 
        false /* replace with evaluation of some actual condition */ 
    }
    
    def printProcessOutput(proc, millis, condition) {
        def queue = new java.util.concurrent.LinkedBlockingQueue()
        def out = new StreamReader(new InputStreamReader(proc.inputStream), queue)
        def err = new StreamReader(new InputStreamReader(proc.errorStream), queue)
    
        def outThread = new Thread(out); outThread.start()
        def errThread = new Thread(err); errThread.start()
    
    
        def start = System.currentTimeMillis()
        def end = start
        def count = 0
        while (end < start + millis) {
            def line = queue.poll(10, java.util.concurrent.TimeUnit.MILLISECONDS)
            if (line) {
                println line
                count++
                if (condition(line, count)) {
                    break
                }
            }
            end = System.currentTimeMillis()
        }
    
        out.kill(); try { outThread.interrupt() } catch (ex) { }
        err.kill(); try { errThread.interrupt() } catch (ex) { }
    
        def temp = []
        queue.drainTo(temp)
        temp.each { println "TEMP: $it" }
    }
    
    class StreamReader implements Runnable {
        final def reader
        final def queue
        volatile def killed = false
    
        public StreamReader(reader, queue) {
            this.reader = reader
            this.queue = queue
        }
    
        def void run() {
            def buff = new BufferedReader(reader)
            def line = buff.readLine()
    
            while (!killed && line != null) {
                queue.offer(line)
                line = buff.readLine()
            }
        }
    
        def kill() {
            killed = true
        }
    }
    

    test.groovy文件很简单:

    def rand = new Random()
    
    def delta = 5 * 60 * 1000
    def start = System.currentTimeMillis()
    def end = start
    
    while (end < start + delta) {
        if (rand.nextBoolean()) {
            System.err.println("ERR " + new Date())
        } else {
            System.out.println("OUT " + new Date())
        }
        Thread.sleep(100)
        end = System.currentTimeMillis()
    }
    println "Done"
    
    1 回复  |  直到 15 年前
        1
  •  1
  •   Joshua Davis    14 年前

    这似乎是可行的。一些可以进一步简化的建议:

    1. 如果不需要队列中的值,则线程可以检查该条件并发出倒计时闩锁信号。