Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to cancel an ExecutorService in java

I wrote an application that runs some threads using ExecutorService and waits until they finish like this:

ExecutorService exService;
exService = Executors.newCachedThreadPool();
exService.execute(T1);
exService.execute(T2);
exService.shutdown();
boolean finshed = exService.awaitTermination(5, TimeUnit.MINUTES);

sometimes I need to cancel the execution of these threads (The entire ExecutorService).
I tried exService.shutdownNow() but it throws java.lang.InterruptedException and doesn't cancel threads.
How can I cancel execution of these threads?


EDIT: T1 class code added as nanda's request

public class TC implements Runnable{
    private ExtractedDataBuffer Buffer;
    private Scraper scraper;
    private String AppPath;
    private boolean Succeed=false;
    private Map<String,Object> Result=null;
    private JLabel StatElement;

    public TC(ExtractedDataBuffer Buffer,String AppPath,String XMLfile,JLabel Stat) throws FileNotFoundException {
        this.Buffer = Buffer;
        this.AppPath=AppPath;
        this.StatElement=Stat;

        ScraperConfiguration config;
        config = new ScraperConfiguration(AppPath + Main.XMLFilesPath +XMLfile);
        scraper = new Scraper(config, AppPath);
    }

    private void extract(){
        try{
            mainF.SetIconStat("working", this.StatElement);
            scraper.execute();
            if(scraper.getStatus()==Scraper.STATUS_FINISHED){
                this.Succeed=true;
                Map<String,Object> tmp=new HashMap<String,Object>();
                tmp.put("UpdateTime", ((Variable) scraper.getContext().get("UpdateTime")).toString().trim());
                Buffer.setVal(this.Result);
                mainF.SetIconStat("done", this.StatElement);
            }else{
                this.Succeed=false;
                this.Result=null;
                Buffer.setVal(null);
                mainF.SetIconStat("error", this.StatElement);
            }
        }catch(Exception ex){
            this.Succeed=false;
            this.Result=null;
            Buffer.setVal(null);
            mainF.SetIconStat("error", this.StatElement);
        }
    }

    public void run() {
        this.extract();
    }    
}
like image 520
Ariyan Avatar asked Dec 22 '22 06:12

Ariyan


2 Answers

If you change shutdown() to shutdownNow(), you are doing the correct thing in the code that you wrote. But then, check the documentation of shutdownNow():

There are no guarantees beyond best-effort attempts to stop processing actively executing tasks. For example, typical implementations will cancel via Thread.interrupt(), so any task that fails to respond to interrupts may never terminate.

So probably your T1 and T2 are not coded in a correct way and don't respond to the interrupt well enough. Can you maybe copy the code for them?

--

Based on your code, I guess the code that takes long time is scraper.execute(), right? So inside those method, you have to constantly check something like this:

if (Thread.interrupted()) {
   throw new InterruptedException();
}

If the interrupt come, the InterruptedException will be thrown and catched in your catch statement and the thread will stop.

like image 90
nanda Avatar answered Dec 24 '22 00:12

nanda


My problem with Future#cancel() is that subsequent calls to get() throw a CancellationException. Sometimes I still want be able to call get() on the Future in order to retrieve a partial result after the shutdown of the executor service. In that case one can implement the termination logic in the callables that you submit to the executor service. Use a field like

private volatile boolean terminate;

public void terminate() {
    terminate = true;
}

and check for terminate in the callable as often as required. In addition, you have to remember your callables somewhere so you can call terminate() on all of them.

like image 38
Ingo Kegel Avatar answered Dec 24 '22 01:12

Ingo Kegel