kimathie
kimathie

Reputation: 426

Which is the neatest and/or most effective approach to kill a thread

I have a task x that is executed continuously in a thread which will only stop when the boolean changes it's state to true. I have done some reading and there are 3 ways that I approach when killing threads that are in the code below. Which of the 3 methods is effective ? And if none of them aren't effective or correct kindly suggest a proper approach with some code for reference.

Below is the code :

public class MyTest {

private static class transaction {

     private String param1,param2,param3, param4, param5;

     public transaction (String param1,String param2,String param3,String param4,String param5){
         this.param1=param1;
         this.param2=param2;
         this.param3=param3;
         this.param4=param4;
         this.param5=param5;
     }

     public String getParam1(){
         return this.param1;
     }

     public String getParam2(){
         return this.param2;
     }

     public String getParam3(){
         return this.param3;
     }

     public String getParam4(){
         return this.param4;
     }

     public String getParam5(){
         return this.param5;
     }
}

public static void processBatch(String workerName){

    try{

        java.util.List <transaction> transactions= new java.util.LinkedList<transaction>();
        java.sql.ResultSet dbtrx=Database.db.execQuery((Object)"dbname.procname");

        while(dbtrx.next()){// Takes a snapshot of the pending payments in the table and stores it into the list.
            Object obj=new transaction (dbtrx.getString("col1"), dbtrx.getString("col2"), dbtrx.getString("col3"), dbtrx.getString("col4"), dbtrx.getString("col5"));
            transactions.add((transaction)obj);
            obj=null;
        }

        java.util.Iterator<transaction> iterate= transactions.iterator();

        /* Processes the pending batch payments*/
        while(iterate.hasNext()){
            transaction trx=iterate.next();
            /*Calls posting function here*/
            System.out.println(workerName+":- Param1 : "+trx.getParam1()+" - Param2 : " +trx.getParam2()+
                    " - Param3 : "+ trx.getParam3()+" - Param4 : "+ trx.getParam4()+" - Param5 : "+ trx.getParam5());
            iterate.remove();
        }

        /*cleaning object references*/
        dbtrx=null;
        transactions=null;
        iterate=null;

     }catch(Exception e){
        e.printStackTrace();
     }
}

public static void main(String [] args) throws InterruptedException{
    volatile boolean stop=false;
    Object hold= new Object();
    new Thread("Batch Worker A"){
        @Override 
        public void run(){
            while(true){
                if(stop!=true){
                    processBatch(Thread.currentThread().getName());
                }else{
                    try{
                    Thread.sleep(0);
                    Thread.currentThread().interrupt();
                    }catch(java.lang.InterruptedException e){
                        Thread.currentThread().interrupt(); 
                        break;
                    }
                }
            }
        }}.start();

    new Thread("Batch Worker B"){
        @Override 
        public void run(){
            try{
                while(stop!=true){
                    processBatch(Thread.currentThread().getName());
                }
                Thread.sleep(0);
                Thread.currentThread().interrupt();
            }catch(java.lang.InterruptedException e){
                Thread.currentThread().interrupt(); 
            }
        }}.start();

    new Thread("Batch Worker C"){
        @Override 
        public void run(){
            while(!Thread.currentThread().isInterrupted()){
                if(stop!=true){
                    processBatch(Thread.currentThread().getName());
                }else{
                    Thread.currentThread().interrupt();
                }
            }
        }}.start();
    }
}

}

Upvotes: 2

Views: 192

Answers (3)

Alon Bar David
Alon Bar David

Reputation: 1727

In all of your examples, you aren't really killing the thread, you are stopping the batch from processing more items. To understand the difference, note that none of your methods would actually stop the thread while the thread is within the processBatch function.

There are some things to take note of:

  • There is no point in calling Interrupt() on your current thread. The idea behind Interrupt is for external threads to call it. In your case, you can just as well throw an exception, or return from the run() function (which would shut down the thread automatically).
  • Even interrupt() can't in many situations stop a thread if that thread is locked outside java ,such as thread waiting for IO (if not using NIO), including a socket, which is what the database connection is, you'll need to design a different way to stop a thread inside IO (usually by doing a timeout, but there are other ways).

if you goal is simply to stop the next batch from happing use the code from Joonas :

new Thread("Batch Worker A"){
@Override 
public void run() {
    while(!stop){
            processBatch(Thread.currentThread().getName());
        }
    }
}}.start();

if your goal is to interrupt the process while running the batch, you can just as well do:

public static void main(String[] args) {
   var t =new Thread("Batch Worker A"){
      @Override 
      public void run() {
         processBatch(Thread.currentThread().getName());
       }
   }.start(); 
   t.interrupt();
}

in general interrupt is the preferred method, and using a local scoped variable and anonymous classes is a really bad idea (use a static variable, or better an injected interface with a function to check if the thread should continue).

Upvotes: 1

Joonas Pulakka
Joonas Pulakka

Reputation: 36577

Why not simply this way:

new Thread("Batch Worker A"){
    @Override 
    public void run() {
        while(!stop){
                processBatch(Thread.currentThread().getName());
            }
        }
    }}.start();

Alternatively, use Thread.interrupt() like so:

new Thread("Batch Worker A"){
    @Override 
    public void run() {
        while(!interrupted()){
                processBatch(Thread.currentThread().getName());
            }
        }
    }}.start();

but then you need to keep reference to all the threads, and interrupt them all, so the boolean flag might be simpler (be sure to make it volatile).

Upvotes: 3

Ted Hopp
Ted Hopp

Reputation: 234795

The recommended approach is to use the thread's interrupted flag to signal the thread loop to terminate. There's no reason to use two flags (stopped and the interrupted flag) where one will do, and you don't seem to be using the interrupted flag for anything else.

See the Java tutorial subject Interrupts for a more extensive discussion and examples.

Upvotes: 6

Related Questions