2015-11-13 29 views
6

Mam program GUI, który wykonuje skrypty automatyzacji TestNG. Jest przeznaczony dla użytkowników do łatwego konfigurowania niektórych ustawień i uruchamiania skryptów automatyzacji, których potrzebują.Zatrzymywanie uruchomionego procesu za pośrednictwem interfejsu GUI, w java

Jedna rzecz, którą muszę dodać, to możliwość natychmiastowego zatrzymania działającego procesu TestNG. Coś jak w Eclipse, przycisk "Zakończ" natychmiast zatrzyma wszystko, co działa.

To co kod, który uruchamia testy TestNG wygląda następująco:

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

Zgodnie z uwag, tng.run() może potrwać kilka minut, aby zakończyć, i to wykonując kilka rzeczy, okna otwarcie przeglądarki/zamykania, itp.

Jak mogę natychmiast zakończyć proces, tak jak w przypadku uruchamiania aplikacji z IDE?

EDIT:

Per komentarzach, ja próbuje użyć ServiceExecutor i shutDownNow() Kod patrzy tak:

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 
} 
+0

System.exit (0); natychmiast zakończy JVM – Olu

+0

@OluCode Tak, ale czy to też nie zabije mojej aplikacji GUI? Potrzebuję sposobu na zabicie działającego obiektu TestNG. – Andrio

+1

jeśli jest to wątek, użyj menedżera wątków, takiego jak ExecutorService, aby obsłużyć żywotność wątku i wywołaj serviceObject.shutDownNow(); – Olu

Odpowiedz

1

Ostatnio pracowałem nad strukturą wykonawczą. Tutaj podałem mój problem http://programtalk.com/java/executorservice-not-shutting-down/

Należy zachować ostrożność, jeśli wykonujesz niektóre operacje we/wy, usługa executora może nie zostać natychmiast zamknięta. Jeśli widzisz poniższy kod stopThread jest ważny, ponieważ informuje program, że wątek został poproszony o zatrzymanie. I możesz zatrzymać niektóre iteracje, co robisz. będę zmodyfikować kod tak:

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

}

3

Spawn proces JVM dziecko używając ProcessBuilder lub Runtime i będzie móc zakończyć ten proces, gdy użytkownik zażąda, aby skrypt przestał działać.

1

Zapisz wszystkie utworzone procesy i zabić je, gdy program kończy:

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

ten można poprawić przez dodanie mechanizmu, który usuwa martwe już procesów, ale można uzyskać ogólne pojęcie.

2

Możesz użyć ExecutorService, aby rozpocząć wykonywanie testu w jeden wątek. Możesz wybrać wiele wątków w równoległym lub juste jeden wątek dla wszystkich testów w sekwencji, wybierając usługę executora, czego potrzebujesz.

Następnie należy rozpocząć wykonywanie wszystkich testów w tej samej instancji usługi executora, wywołując metodę submit() na tej instancji. Możesz zatrzymać wykonywanie wszystkich przesłanych runnables, wywołując metodę shutdownNow().

Ważne jest, aby użyć tego samego wystąpienia ExecutorService, w przeciwnym razie rozpoczniesz każdy test w innym wątku i nie będziesz mógł przerwać łańcucha wykonawczego (lub wywołując shutdownNow() na każdym z nich).

1

Co o tym dodać lotny logiczną statyczne i uczynić wygląd kodu wątek jak ...

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 
} 

Teraz można dodać przycisk w głównym interfejsem graficznym, który po prostu ustawia runThread false więc Wątek zakończy się prawie natychmiast, pozostawiając cały pozostały kod nietknięty po naciśnięciu przycisku 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(); 
    } 
} 
1

Co powiecie na nowy wątek?Trzeba dodać private Thread thread; w GUI i kiedy tylko zaczniesz

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

i przestać „zakończyć”

thread.stop(); (depracted) lub thread.setDeamon(true);

Everytime muszę zatrzymać proces przez gui Używam tego.

Nadzieja mogłem pomóc;)

1

W swojej GUI gdzieś masz coś

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

Gdy chcesz, aby zatrzymać go nazwać

scriptRunner.interrupt(); 

zmienić kod w ScriptRunner

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

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