代码之家  ›  专栏  ›  技术社区  ›  John Doe

取消eclipse插件作业

  •  1
  • John Doe  · 技术社区  · 7 年前

    我在eclipse插件中运行 Job 一种执行长时间操作而没有太多输出的过程。
    我想取消 工作 如果用户请求,但在下面的实现中 工作 除非进程将某些内容打印到输出流,否则不会停止。

    Process process = new ProcessBuilder(args).start();
    Scanner scanner = new Scanner(
                    (new InputStreamReader(
                            process.getInputStream(), UTF_8_CHARSET)));
    
    while (scanner.hasNext())
    {
    
        if (monitor.isCanceled() {
            // user canceled the job, destroy the process to return
            process.destroy();
            break;
        }
    
        CONSOLE.getStream().println(scanner.nextLine());
    
    }
    
    try {
        process.waitFor();
    
    } catch (InterruptedException e) {
    
        Activator.log(ERROR, e.getMessage(), e);
    
    } finally {
        process.destroyForcibly();
    }
    

    我是否有其他选择来处理取消作业,并更快地停止进程,而不是等待新的换行?

    3 回复  |  直到 7 年前
        1
  •  4
  •   greg-449    7 年前

    您应该将读取进程输出流的代码放入一个单独的线程中,并在主循环中等待进程以短时间超时结束,以便检查是否已取消。

    所以主代码应该是这样的:

    Process process = new ProcessBuilder(args).start();
    
    // Read standard output
    new StreamConsumer(process.getInputStream()).start();
    
    // You should also always read stderr
    new StreamConsumer(process.getErrorStream()).start();
    
    // Wait for process to end and check for cancel
    
    while (!process.waitFor(100, TimeUnit.MILLISECONDS) {
      if (monitor.isCanceled() {
        // user canceled the job, destroy the process to return
        process.destroy();
        break;
      }
    }
    

    StreamConsumer 类似于:

    public class StreamConsumer extends Thread
    {
      private final InputStream _input;
    
      public StreamConsumer(final InputStream inputStream)
      {
        super();
    
        _input = inputStream;
    
        setDaemon(true);
      }
    
    
      @Override
      public void run()
      {
        // TODO your code to read the stream
      }
    }
    
        2
  •  1
  •   Ben    7 年前

    而不是 Scanner 使用 BufferedReader 它提供了 ready 方法,这是一种非阻塞方式,用于告诉您是否有要读取的内容,而不是使用扫描仪 nextLine() 它会一直阻塞,直到有东西被真正读取。

    小示例实现:

    volatile static boolean stop = false;
    
    public static void main(String[] args) throws InterruptedException
    {
        // Create a new thread that reads input from System.in
        new Thread(() -> {
    
            BufferedReader read = new BufferedReader(new InputStreamReader(System.in));
            while (!stop)
            {
                try
                {
                    // If there is something to read read it and print it
                    if (read.ready())
                    {
                        System.out.println(read.readLine());
                    }
                }
                catch (IOException e)
                {
                    // Do some handling...
                }
            }
    
        }).start();
    
        // Wait 5 seconds then stop the thread by making the flag false.
        Thread.sleep(5000);
        stop = true;
    }
    

    您的标志显然随流程一起提供。要点是使用非阻塞操作(如果确实有要打印的内容,请查看),而不是使用阻塞操作。

        3
  •  0
  •   Markus Hettich    5 年前

    就我而言,我不知道这个过程要持续多久。所以超时是没有选择的。 我的另一种解决方案是启动一个单独的监视线程,监视 IProgressMonitor . 如果进度监视器处于取消状态,则执行线程被中断。

    public static void startMonitorThread(IProgressMonitor monitor) {        
        final Thread runThread = Thread.currentThread();                     
        new Thread("Monitor") {                                              
            @Override                                                        
            public void run() {                                              
                while (runThread.isAlive() && !monitor.isCanceled()) {       
                    try {                                                    
                        Thread.sleep(100);                                   
                    } catch (InterruptedException exception) {               
                        break;                                               
                    }                                                        
                }                                                            
                if (runThread.isAlive()) {                                   
                    runThread.interrupt();                                   
                }                                                            
            };                                                               
        }.start();                                                           
    }                                                                        
    

    下一个代码段显示了如何使用此功能的示例:

    startMonitorThread(monitor);                                                                       
    
    final Process process = new ProcessBuilder("...").start();                                         
    try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
        while (process.isAlive()) {                                                                    
            if (reader.ready()) {                                                                      
                final String line = reader.readLine();                                                 
                // ... do something with line                                                          
            } else {                                                                                   
                Thread.sleep(10);                                                                      
            }                                                                                          
        }                                                                                              
    }                                                                                                  
    

    首先,我犯了同样的错误,使用了一个阻塞的扫描仪(而中断没有起作用)。就像Ben的回答提到的那样,最好使用 BufferedReader 和非阻塞 ready() 方法检查是否有更多内容要读取。