简体   繁体   中英

How to interrupt a long running process - Java

I have a GUI with a 'process' button. When the button is pressed, the following code is executed:

//Check for results truncation
boolean truncate = !jCheckBoxTruncate.isSelected();
String[] args = {fileName};
//run solution and draw graph
SpeciesSelection specSel = new SpeciesSelection(args, truncate);
Thread t = new Thread(specSel);
t.start();
long startTime = System.nanoTime();
cancelled = false;
jButtonCancel.setVisible(true);

new Thread() {
  @Override
  public void run() {
    while (!specSel.isFinished() && !cancelled) {
       double seconds = (System.nanoTime() - startTime) / 1000000000.0;
       jLabelProcessTime.setText("Processing Time: " + toTimeString(seconds));
       try {
          Thread.sleep(91);
       } catch (InterruptedException ex) {
          Logger.getLogger(SpecSelGUI.class.getName()).log(Level.SEVERE, null, ex);
       }
   }

jButtonCancel.setVisible(false);
jButtonProcess.setEnabled(true);
// If processing finished then display result graph, else the process was cancelled so stop the processing thread.
if (specSel.isFinished()) {
   ArrayList<Double> result = specSel.getResult();
   drawGraph(result);
}
else {
       t.interrupt();
     }
   }
}.start();

So I have a 'Thread t' that executes a long running process, and an anonymous thread that just updates the processing time on the GUI and monitors for a request to cancel Thread t. The SpeciesSelection class overrides run() as follows:

@Override
public void run() {
   long start = System.nanoTime();
   try {
       result = specSel(args, truncate);//VERY LONG RUNNING PROCESS CALLED ONCE
   } catch (FileNotFoundException ex) {
       Logger.getLogger(SpeciesSelection.class.getName()).log(Level.SEVERE, null, ex);
   }
   finished = true;
       System.out.println("Process took " + ((System.nanoTime() - start) / 1000000.0) + "ms");
   }

I have a cancel button that sets the flag 'cancelled' to true. In the event that this button is pressed I attempt to interrupt Thread t. However, nothing happens and the thread continues to run. I think I'm missing something and would appreciate some help on how to properly interrupt the long running process/Thread t.

I guess specSel(args, truncate);//VERY LONG RUNNING PROCESS CALLED ONCE doesn't support interruption.

For the interrupt mechanism to work correctly, the interrupted thread must support its own interruption.

How does a thread support its own interruption?

  1. If the thread is frequently invoking methods that throw InterruptedException (like Thread.sleep() ), you can handle the interrupt inside the ExceptionHandler like

     try { Thread.sleep(4000); } catch (InterruptedException e) { // We've been interrupted: no more messages. return; } 
  2. What if a thread goes a long time without invoking a method that throws InterruptedException? Then it must periodically invoke Thread.interrupted, which returns true if an interrupt has been received. For example:

     for (int i = 0; i < inputs.length; i++) { if (Thread.interrupted()) { // We've been interrupted: no more crunching. return; } } 

Since latter be the case of you, I suggest you do the second suggestion inside specSel(args, truncate); to support its interruption. Of course, you can do something else other than return . But this is what you wanted.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM