Valter Silva
Valter Silva

Reputation: 16656

How interrupt/stop a thread in Java?

I'm trying to stop a thread but I can't do that :

public class Middleware {

public void read() {
    try {
        socket = new Socket("192.168.1.8", 2001);

        // code .. 

        Scan scan = new Scan();
        thread = new Thread(scan);
        thread.start();

    } catch (UnknownHostException ex) {
        ex.printStackTrace();

    } catch (IOException ex) {
        ex.printStackTrace();
    }
}

class Scan extends Thread {

    public void run() {

        while (true) {
            try {
            // my code goes here

            } catch (IOException ex) {
                thread.currentThread().interrupt();
            }
        }
    }
}

public void stop() {
    Thread.currentThread().interrupt();
}

// get and setters
}

So, even when i call the method 'stop' the thread don't stop. It keeps alive.

How can I interrupt/stop this thread ?

UPDATE (@little approach)

private void tb_startActionPerformed(java.awt.event.ActionEvent evt) {                                         
    Middleware middleware = new Middleware();

    if (tb_start.getText().equals("Start")){
        tb_start.setText("Stop");

        // starting to read rfid tags
        middleware.read();
    }else{
        tb_start.setText("Start");

        // stop reading rfid tags
        middleware.stop();
    }
}

The Middleware class :

public class Middleware {

    private Scan scan;

    public void read() {

        scan = new Scan();
        scan.start();
    }

    private class Scan extends Thread {

        @Override
        public void run() {
            while (!Thread.currentThread().isInterrupted()) {
                System.out.println("reading...");
            }
        }
    }

    public void stop() {
        if (scan != null) {
            scan.interrupt();
        }
    }
}

But when I try to stop the thread, it doesn't.

What could be wrong in the code above ?

Upvotes: 16

Views: 63249

Answers (8)

Anantha Sharma
Anantha Sharma

Reputation: 10098

if you want to interrupt a running thread, then you need to have access to the thread object.

thread = new Thread(scan);
thread.start();

then say

thread.interrupt();

this will interrupt the running thread.

Upvotes: 5

wandermonk
wandermonk

Reputation: 7356

Rather than using Thread.stop() or Thread.interrupt() you can go for the external locks. Basically, when you try to utilize an intrinsic lock most of the time any interrupt you perform on the thread is uncontrollable.

A re-entrant lock provides you the methods as mentioned below

lock() 
unlock() 
tryLock() 
lockInterruptibly() 
isHeldByCurrentThread() 
getHoldCount() 

Check the below example

final ReentrantLock reentrantLock = new ReentrantLock();    
    @Override
    public void performTask() {
        reentrantLock.lock();
        try { 
             System.out.println(Thread.currentThread().getName() + ": Lock acquired.");
             System.out.println("Processing...");
             Thread.sleep(2000);
        } catch (InterruptedException e) {
             e.printStackTrace();
        } finally {
             System.out.println(Thread.currentThread().getName() + ": Lock released.");
         reentrantLock.unlock();
            }
    }

This makes your code elegant and handle the interrupt in a better way.

Upvotes: 0

Sylver
Sylver

Reputation: 11

    public void run()
    { 
         while (!Thread.currentThread().isInterrupted()) 
         {
        //do something here
        if(condition)
       {
           Thread.currentThread().interrupt();
       }
   }

Upvotes: 0

trashgod
trashgod

Reputation: 205785

"Many uses of stop() should be replaced by code that simply modifies some variable to indicate that the target thread should stop running."—java.lang.Thread

Upvotes: 5

Osama Javed
Osama Javed

Reputation: 1442

Completely agree with Jim.. Just to add If your thread is blocked inside the try block for instance reading on a datastream etc then interrupt the thread as well or close the stream. In both cases the thread should be wakened up again and it will then be able to see the change in the value of "stop" boolean and die naturally by falling out of the run method. At least this is what I did to kill my threads in the shutdown thread for my server.

Upvotes: 1

mre
mre

Reputation: 44240

There's really no reason you need to use a volatile flag. Instead, just query the thread for its state with isInterrupted(). Also, why are you wrapping your Scan thread object in another thread object? That seems completely unnecessary to me.

Here' what you should be doing

public class Middleware {
    private Scan scan;

    public void read() {
        try {
            // do stuff

            scan = new Scan();
            scan.start();
        } catch (UnknownHostException ex) {
            // handle exception
        } catch (IOException ex) {
            // handle exception
        }
    }

    private class Scan extends Thread {

        @Override
        public void run() {
            while (!Thread.currentThread().isInterrupted()) {
                try {
                    // my code goes here
                } catch (IOException ex) {
                    Thread.currentThread().interrupt();
                }
            }
        }
    }

    public void stop() {
        if(scan != null){
            scan.interrupt();
        }
    }
}

Here's an example. Also, I wouldn't recommend extending Thread.

Upvotes: 21

Leonard Brünings
Leonard Brünings

Reputation: 13222

Simply return; from your while and the thread will die, no need to call stop() or interrupt(). If you want to do it externally then use this pattern and call requestStop().

class Scan extends Thread {
    private volatile stop = false;
    public void run() {

        while (!stop) {
            try {
            // my code goes here

            } catch (IOException ex) {
                stop = true;
            }
        }
    }

    public void requestStop() {
        stop = true;
    }

}

Upvotes: 11

Jim
Jim

Reputation: 22656

The usual way to stop a thread is to have a volatile flag and then check that in the run method. i.e.

class Scan extends Thread {
    volatile stop = false;
    public void run() {

        while (!stop) {
            try {
            // my code goes here

            } catch (IOException ex) {
                thread.currentThread().interrupt();
            }
        }
    }

    public void stop(){
        stop = true;
    }
}

You can then call scan.stop().

Upvotes: 5

Related Questions