Reputation: 16656
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
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
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
Reputation: 11
public void run()
{
while (!Thread.currentThread().isInterrupted())
{
//do something here
if(condition)
{
Thread.currentThread().interrupt();
}
}
Upvotes: 0
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
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
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
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
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