在 java 中通过 GUI 停止 运行 进程

Stopping a running process via GUI, in java

我有一个执行 TestNG 自动化脚本的 GUI 程序。这意味着用户可以轻松配置一些设置并启动他们想要的自动化脚本。

我需要添加的一件事是立即停止 运行 TestNG 进程的能力。就像在 Eclipse 中一样,'Terminate' 按钮将立即停止任何 运行.

启动 TestNG 测试的代码如下所示:

public class ScriptRunner implements Runnable {

    public void runScript() {
        Thread testRun = new Thread(this);
        testRun.start();
    }

    @Override
    public void run() {
        //various other things are configured for this, 
        //but they're not relevant so I left them out
        TestNG tng = new TestNG();

        //While this runs, various browser windows are open, 
        //and it could take several minutes for it all to finish
        tng.run();
    }
}

根据评论,tng.run() 可能需要几分钟才能完成,它正在执行几件事,opening/closing 浏览器 windows,等等

我怎样才能立即终止进程,就像 运行 来自 IDE 的应用程序一样?

编辑:

根据评论,我正在尝试使用 ServiceExecutor 并且 shutDownNow() 代码如下所示:

ExecutorService executorService = Executors.newFixedThreadPool(10);

public void runScript() {
    executorService.execute(this);
}

//this method gets called when I click the "stop" button
public void stopRun() {
    executorService.shutdownNow();
}

@Override
public void run() {
    //same stuff as from earlier code
}

使用 ProcessBuilder 或 Runtime 生成子 JVM 进程,当用户请求脚本停止时,您将能够终止该进程 运行。

保存所有创建的进程并在程序结束时终止它们:

public class ProcessFactory {
  private static Set<Process> processes = new HashSet<>();
  private static boolean isRunning = true;

  public static synchronized Process createProcess(...) throws ... {
    if (!isRunning)
      throw ...
    ... // create your spawned process
    processes.add(process);
    return process;
  }

  public static synchronized void killAll() {
    isRunning = false;
    for (Process p : processes)
        p.destroy();
    processes.clear();
  }

  public static void registerShutdownHook() {
      Runtime.getRuntime().addShutdownHook(new Thread() {
         void run() {
             killAll();
         }
      });
  }
}

这可以通过添加一种机制来改进,该机制可以删除已经死掉的进程,但您已经了解了总体思路。

您可以使用 ExecutorService 开始测试执行到另一个线程。通过选择您需要的执行程序服务,您可以选择并行使用多个线程,也可以按顺序为所有测试设置一个线程。

之后,通过调用 submit() 方法在同一执行器服务实例中开始执行所有测试。您可以通过调用 shutdownNow() 方法停止所有提交的可运行程序的执行。

使用相同的 ExecutorService 实例很重要,否则您将在不同的线程中启动每个测试,并且您将无法中断执行链(或通过对所有这些实例调用 shutdownNow())。

这个呢, 添加一个 volatile static boolean 并使线程代码看起来像...

if(ScriptRunner.runThread){
    //Do some stuff here
}
if(ScriptRunner.runThread){
    //Do some other stuff here
}
if(ScriptRunner.runThread){
    //Do some other stuff here
}
if(ScriptRunner.runThread){
    //Do rest of the stuff here
}

现在您可以在主 GUI 中添加一个按钮,该按钮只需将 runThread 设置为 false,这样线程将几乎立即终止,而在您按下 Stop 按钮时保留所有剩余代码。

public class ScriptRunner implements Runnable {

    volatile static Boolean runThread = true;

    public void runScript() {
        Thread testRun = new Thread(this);
        testRun.start();
    }

    public void terminate(){
        runThread = false;
    }

    @Override
    public void run() {
        //various other things are configured for this, 
        //but they're not relevant so I left them out
        TestNG tng = new TestNG();

        //While this runs, various browser windows are open, 
        //and it could take several minutes for it all to finish
        tng.run();
    }
}

新线程怎么样?你必须在 gui 中添加一个 private Thread thread; 并且你什么时候开始

thread = new thread(){
    @Override
    public void run(){
       //start process here
    }
};
thread.start();

并停止"terminate"

thread.stop();(堕落)或thread.setDeamon(true);

每次我必须通过 gui 停止进程时,我都会使用它。

希望我能帮到你 ;)

在你的 GUI 某处你有类似的东西

ScriptRunner scriptRunner = new ScriptRunner();
scriptRunner.runScript();

想停止时调用

scriptRunner.interrupt();

更改ScriptRunner中的代码

private Thread testRun;
public void runScript() {
    testRun = new Thread(this);
    testRun.start();
}

public void interrupt() {
    testRun.interrupt();
}

我最近在研究执行器框架。在这里我列出了我的问题 http://programtalk.com/java/executorservice-not-shutting-down/

如果您正在执行某些 IO 操作,请注意执行程序服务可能不会立即关闭。如果你看到下面的代码 stopThread 很重要,因为它告诉你的程序线程已被要求停止。你可以停止你正在做的一些迭代。 我将这样修改您的代码:

public class MyClass {

private ExecutorService executorService;

private boolean stopThread = false;

public void start() {
   // gives name to threads
    BasicThreadFactory factory = new BasicThreadFactory.Builder()
             .namingPattern("thread-%d").build();
    executorService =  Executors.newSingleThreadExecutor(factory);
    executorService.execute(new Runnable() {
        @Override
        public void run() {
            try {
                doTask();
            } catch (Exception e) {
                logger.error("indexing failed", e);
            }

        }
    });
    executorService.shutdown();
}

private void doTask()  {
    logger.info("start reindexing of my objects");
    List<MyObjects> listOfMyObjects = new MyClass().getMyObjects();
    for (MyObjects myObject : listOfMyObjects) {
        if(stopThread){ // this is important to stop further indexing
            return;
        }
        DbObject dbObjects = getDataFromDB();
        // do some task
    }
}



public void stop() {
    this.stopThread = true;
    if(executorService != null){
        try {
            // wait 1 second for closing all threads
            executorService.awaitTermination(1, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
}

}