Java: waiting thread notified abnormally - java

I am using a "transceiver" to send a request from the client to the server and wait for the response. I learned from [here][1] the way to communicate between two threads and wrote bellow codes:
public class ThreadEvent {
private Object lock;
private Object data;
private String ntfInfo;
public ThreadEvent() {
data = null;
lock = new Object();
ntfInfo = "NONE";
}
public boolean await(int time) {
synchronized (lock) {
try {
lock.wait(time);
return true;
} catch (InterruptedException ex) {
LogManager.ex(ex);
return false;
}
}
}
public void signal() {
synchronized (lock) {
ntfInfo = (new Throwable()).getStackTrace()[1].getMethodName() + "#"
+ (new Throwable()).getStackTrace()[1].getClassName() + "#"
+ "line" + (new Throwable()).getStackTrace()[1].getLineNumber() + "#"
+ (new Throwable()).getStackTrace()[1].getFileName();
lock.notify();
}
}
public synchronized void putData(Object data) {
this.data = data;
}
public synchronized Object takeData() {
Object res = data;
data = null;
return res;
}
public String takeNtfInfo() {
String info = ntfInfo;
ntfInfo = "NONE";
return info;
}
}
I found sometimes the send-and-wait thread was not always been notified by the response, nor been interrupted, (as per my understanding) but was awaked from the wait by some mysterious "thing". Here is the log:
1460717223039:DEBUG:1 starting... #<init>#wsclientapp.GUIManager#line57#GUIManager.java
1460717229475:DEBUG:2 transceive()#line30#WSTransceiver.java
1460717229735:DEBUG:3 forward()#line69#WSTransceiver.java
1460717229739:DEBUG:4 transceive(ivoked by: forward#wsclientapp.util.WSTransceiver#line73#WSTransceiver.java)#line42#WSTransceiver.java
1460717229750:DEBUG:5 transceive()#line30#WSTransceiver.java
1460717229768:DEBUG:6 forward()#line69#WSTransceiver.java
1460717229768:DEBUG:7 transceive(ivoked by: forward#wsclientapp.util.WSTransceiver#line73#WSTransceiver.java)#line42#WSTransceiver.java
1460717229770:DEBUG:8 transceive()#line30#WSTransceiver.java
1460717234771:DEBUG:9 transceive(ivoked by: NONE)#line42#WSTransceiver.java
You may see line2/3/4 is a transaction, and line5/6/7 is another transaction, but line8/9 shows the problem. If the transceive was awaked by someone, it should print the name of the thread, or if it's been interrupted, it should print the exception stack by the LogManager.ex(ex). But it didn't. What I did wrong?

When you call notify() only a thread which is waiting will be notified. If the threads are doing something else, the notify is lost.
When you call wait() it can wake spuriously.
In short;
only notify after a state change.
only wait in a while loop where you check that state check before waiting.

Related

I'm trying to understand why notifyAll() isn't waking on shared lock

I'm trying to make a method that makes one thread wait until another thread calls that method. The context is having the front end wait for the backend to prepare data to be displayed, and then the backend waiting for user input before preparing the next data to be displayed. The problem I'm having here is that both forks in my method call notifyAll() before calling wait() but the notifyAll() doesn't ever trigger the other to catch the exception. Here's a simplified example that causes the problem I'm facing.
public class Test {
static Object lock = new Object();
static boolean allCaughtUp = false;
static boolean backCaughtUp = false;
static boolean frontCaughtUp = false;
public static void main(String[] args) {
new Thread(new Runnable() {
#Override
public void run() {
catchUp("backend");
}
}).start();
catchUp("frontend");
}
public static void catchUp(String origin){
assert origin.equals("frontend") || origin.equals("backend");
if(origin.equals("frontend")){
System.out.println("frontend origin reached");
synchronized (lock){
while(!allCaughtUp){
lock.notifyAll();
try{
lock.wait();
}catch(InterruptedException e){
System.out.println("backend caught up");
backCaughtUp = true;
lock.notifyAll();
}
if(backCaughtUp && frontCaughtUp){
allCaughtUp = true;
}
}
}
}else {
System.out.println("backend origin reached");
synchronized (lock){
while(!allCaughtUp){
lock.notifyAll();
try{
lock.wait();
}catch(InterruptedException e){
System.out.println("frontend caught up");
frontCaughtUp = true;
lock.notifyAll();
}
if(backCaughtUp && frontCaughtUp){
allCaughtUp = true;
}
}
}
}
}
}
The output I get before the program gets stuck waiting for itself is:
Frontend origin reached
Backend origin reached

Why does multithreaded version take the same amount of time as single threaded version?

I have the following work queue implementation, which I use to limit the number of threads in use. It works by me initially adding a number of Runnable objects to the queue, and when I am ready to begin, I run "begin()". At this point I do not add any more to the queue.
public class WorkQueue {
private final int nThreads;
private final PoolWorker[] threads;
private final LinkedList queue;
Integer runCounter;
boolean hasBegun;
public WorkQueue(int nThreads) {
runCounter = 0;
this.nThreads = nThreads;
queue = new LinkedList();
threads = new PoolWorker[nThreads];
hasBegun = false;
for (int i = 0; i < nThreads; i++) {
threads[i] = new PoolWorker();
threads[i].start();
}
}
public boolean isQueueEmpty() {
synchronized (queue) {
if (queue.isEmpty() && runCounter == 0) {
return true;
} else {
return false;
}
}
}
public void begin() {
hasBegun = true;
synchronized (queue) {
queue.notify();
}
}
public void add(Runnable r) {
if (!hasBegun) {
synchronized (queue) {
queue.addLast(r);
runCounter++;
}
} else {
System.out.println("has begun executing. Cannot add more jobs ");
}
}
private class PoolWorker extends Thread {
public void run() {
Runnable r;
while (true) {
synchronized (queue) {
while (queue.isEmpty()) {
try {
queue.wait();
} catch (InterruptedException ignored) {
}
}
r = (Runnable) queue.removeFirst();
}
// If we don't catch RuntimeException,
// the pool could leak threads
try {
r.run();
synchronized (runCounter) {
runCounter--;
}
} catch (RuntimeException e) {
// You might want to log something here
}
}
}
}
}
This is a runnable I use to keep track of when all the jobs on the work queue have finished:
public class QueueWatcher implements Runnable {
private Thread t;
private String threadName;
private WorkQueue wq;
public QueueWatcher(WorkQueue wq) {
this.threadName = "QueueWatcher";
this.wq = wq;
}
#Override
public void run() {
while (true) {
if (wq.isQueueEmpty()) {
java.util.Date date = new java.util.Date();
System.out.println("Finishing and quiting at:" + date.toString());
System.exit(0);
break;
} else {
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
Logger.getLogger(PlaneGenerator.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
public void start() {
wq.begin();
System.out.println("Starting " + threadName);
if (t == null) {
t = new Thread(this, threadName);
t.setDaemon(false);
t.start();
}
}
}
This is how I use them:
Workqueue wq = new WorkQueue(9); //Get same results regardless of 1,2,3,8,9
QueueWatcher qw = new QueueWatcher(wq);
SomeRunnable1 sm1 = new SomeRunnable1();
SomeRunnable2 sm2 = new SomeRunnable2();
SomeRunnable3 sm3 = new SomeRunnable3();
SomeRunnable4 sm4 = new SomeRunnable4();
SomeRunnable5 sm5 = new SomeRunnable5();
wq.add(sm1);
wq.add(sm2);
wq.add(sm3);
wq.add(sm4);
wq.add(sm5);
qw.start();
But regardless of how many threads I use, the result is always the same - it always takes about 1m 10seconds to complete. This is about the same as when I just did a single threaded version (when everything ran in main()).
If I set wq to (1,2,3--9) threads it is always between 1m8s-1m10s. What is the problem ? The jobs (someRunnable) have nothing to do with each other and cannot block each other.
EDIT: Each of the runnables just read some image files from the filesystems and create new files in a separate directory. The new directory eventually contains about 400 output files.
EDIT: It seems that only one thread is always doing work. I made the following changes:
I let the Woolworker store an Id
PoolWorker(int id){
this.threadId = id;
}
Before running I print the id of the worker.
System.out.println(this.threadId + " got new task");
r.run();
In WorkQueue constructor when creating the poolworkers I do:
for (int i = 0; i < nThreads; i++) {
threads[i] = new PoolWorker(i);
threads[i].start();
}
But it seems that that only thread 0 does any work, as the output is always:
0 got new task
Use queue.notifyAll() to start processing.
Currently you're using queue.notify(), which will only wake a single thread. (The big clue that pointed me to this was when you mentioned only a single thread was running.)
Also, synchronizing on Integer runCounter isn't doing what you think it's doing - runCounter++ is actually assigning a new value to the Integer each time, so you're synchronizing on a lot of different Integer objects.
On a side note, using raw threads and wait/notify paradigms is complicated and error-prone even for the best programmers - it's why Java introduced the java.util.concurrent package, which provide threadsafe BlockingQueue implementations and Executors for easily managing multithreaded apps.

Why is my boolean not being changed?

So I'm trying to create a client/server program. I want to know when my client disconnects of his own accord, so I've setup a heartbeat system. Every 6 seconds my client sends a ping to my server, if the client doesn't send a ping for a total of 30 seconds the client is considered disconnected and removed from the current connections list (for which I plan to implement a GUI). Or at least, that's the plan.
ConnectionManager.java
public class ConnectionManager implements Runnable{
static Socket connection;
private ArrayList<Thread> allConnections;
private ArrayList<Connection> allConnectionList;
private ServerSocket server;
private int id = 0;
public ConnectionManager() {
allConnections = new ArrayList<Thread>();
allConnectionList = new ArrayList<Connection>();
}
#Override
public void run() {
try {
server = new ServerSocket(5555);
System.out.println("Server is running!");
while(true) {
connection = server.accept();
Connection a = new Connection(connection, id);
Runnable runnable = a;
allConnectionList.add(a);
allConnections.add(new Thread(runnable));
allConnections.get(allConnections.size() - 1).start();
id++;
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void removeConnection(int id) {
allConnections.remove(id);
allConnectionList.remove(id);
}
Connection.java
public class Connection implements Runnable {
private Socket a;
public boolean amIActive;
private int id;
public Connection(Socket a, int id) {
amIActive = true;
this.a = a;
this.id = id;
}
public void onConnect() {
try {
String TimeStamp = new java.util.Date().toString();
String formattedAddress = a.getInetAddress().toString().replace("/", "");
System.out.println("Received connection from: " + formattedAddress + " at " + TimeStamp);
Runnable runnable = new ConnectionListener(this);
Thread connectionThread = new Thread(runnable);
connectionThread.start();
String returnCode = "Server repsonded to " + a.getInetAddress().toString().replace("/", "") + " at "+ TimeStamp + (char) 13;
BufferedOutputStream os = new BufferedOutputStream(a.getOutputStream());
OutputStreamWriter osw = new OutputStreamWriter(os, "US-ASCII");
osw.write(returnCode);
osw.flush();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Override
public void run() {
onConnect();
System.out.println("We got this far!");
while(amIActive) {
whileTrue();
}
System.out.println("This code never gets run because we get stuck in the while loop above");
Main.b.removeConnection(id);
System.out.println("Connection was closed from " + a.getInetAddress());
}
public void setOffline(boolean state) {
this.amIActive = state;
}
public void whileTrue() {
}
public Socket getSocket() {
return a;
}
ConnectionListener.java
public class ConnectionListener implements Runnable{
public Connection myConnection;
public boolean receivedHeartbeat;
public int missedHeartbeats = 0;
public ConnectionListener(Connection a) {
this.myConnection = a;
}
#Override
public void run() {
Runnable runnable = new Heartbeat(this);
Thread thread = new Thread(runnable);
thread.start();
while(myConnection.amIActive) {
try {
BufferedInputStream is;
is = new BufferedInputStream(myConnection.getSocket().getInputStream());
InputStreamReader isr = new InputStreamReader(is);
StringBuffer process = new StringBuffer();
int character;
while((character = isr.read()) != 13) { //GETTING STUCK HERE BECAUSE STUPID.
if(character == -1) {
myConnection.setOffline(true);
} else {
process.append((char)character);
}
}
handleInput(process);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void handleInput(StringBuffer process) {
String messageSent = process.toString();
if(messageSent.equals("Ping!")) {
receivedHeartbeat = true;
}
}
Heartbeat.java
public class Heartbeat implements Runnable{
private ConnectionListener b;
public Heartbeat(ConnectionListener a) {
b = a;
}
#Override
public void run() {
while(true) {
try {
Thread.sleep(1000);
if(b.missedHeartbeats > 5) {
b.myConnection.amIActive = false;
System.out.println("Setting amIActiveToFalse!");
}
if(b.receivedHeartbeat) {
b.receivedHeartbeat = false;
} else {
b.missedHeartbeats++;
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
My console is spammed with System.out.println("Setting amIActiveToFalse!"); from Heartbeat.java. But the while loop in Connection.java keeps running. I believe this might be something to do with my threading, but I can't figure it out.
When you have a non-volatile variable, there is no guarentee of visability of a change in one thread to another. In particular, if the JVM detects that a thread doesn't alter a boolean it can inline it, meaning you will never see the value change.
The simple solution is to make the boolean volatile and it will not be inlined and one thread will see when another changes it.
For more details http://vanillajava.blogspot.com/2012/01/demonstrating-when-volatile-is-required.html
The trivial answer to this is: make the variable volatile.
Without this, it is allowed for the thread changing the value to basically keep its updates in cache, committing them to main memory some time later.
This allows threaded code to run much faster, since it can keep its variables in cache rather than having to fetch from main memory. However, the consequence of this is that other threads don't see the update.
Making the variable volatile prevents this from happening: a thread always reads the value from main memory, and writes are immediately committed.
I say that this is the trivial answer because it doesn't necessarily fix all of your problems. There may also be an atomicity issue: in between one thread reading the variable and writing it again, another thread might sneak in and change its value, which may or may not put the first thread into an undefined state from the perspective of its invariants.
Specifically:
if(b.receivedHeartbeat) { b.receivedHeartbeat = false;
It is possible that some other thread can change b.receivedHeartbeat to false after this thread evaluates it to true, so this iteration is erroneously counted as a "non-missed" heartbeat.
This can be fixed by making the variable a (non-volatile) AtomicBoolean, on which there is an atomic compare-and-set method, which avoids such race conditions.
Java Concurrency In Practice is a great reference on these issues, I wholeheartedly recommend it. Look for the topics "visibility" and "atomicity".
Also read the advanced chapter on the Java Memory Model. That made me doubt myself at first, but made me a much stronger programmer after I digested it.
There are a couple issues I saw while debugging the code you posted, but I was able to successfully get the heartbeat functionality working.
In the Connection Listener class I don't think the if statement with .equals("Ping!") will match, because of the newline character at the end of each line.
In the Connection Listener class I would probably put the socket's Input Stream at the top of the loop not inside the loop. (I don't think this will break it but it's probably nicer this way)
ConnectionListener Updates:
public void run() {
Runnable runnable = new Heartbeat(this);
Thread thread = new Thread(runnable);
thread.start();
BufferedReader br = null;
try {
//is = new BufferedInputStream(myConnection.getSocket().getInputStream());
br = new BufferedReader(new InputStreamReader(myConnection.getSocket().getInputStream()));
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
while(myConnection.amIActive) {
try {
String processLine = br.readLine();
System.out.println("handleInput:" + processLine);
handleInput(processLine);
} catch (Exception e) {
System.out.println("Exception!");
e.printStackTrace();
}
}
}
public void handleInput(String messageSent) {
if(messageSent.startsWith("Ping!")) { //Need to use startsWith, or add newline character
receivedHeartbeat = true;
System.out.println("receivedHeartbeat!");
}
}
Also, in your Heartbeat class make sure you reset the missedHeartbeats counter to 0 on true:
if(b.receivedHeartbeat) {
b.receivedHeartbeat = false;
b.missedHeartbeats = 0;
} else {
b.missedHeartbeats++;
}

Java calling Object.notify() before Object.wait() [duplicate]

This question already has answers here:
calling Object.notify() before Object.wait()
(4 answers)
Closed 8 years ago.
i have 2 thread one for transmissions and one for replay
I would like to send one message only when i receive a message on the RXThread. i've used wait() and notify(), and for preventing that a notify came before the wait() i do this, but it only works when run in debug, although the RX thread doesn't send the message.
private boolean stopped = false;
class StubTxtask implements Runnable {
public void run() {
try {
// Sends all messages in sequence
for (int i=0; i<txMsgSeq.getMessagesCount(); i++) {
}
if (syncRxTx) {
synchronized (syncObj) {
while(!stopped) {
syncObj.wait();
}
}
}
System.out.println("************ "+ i + "/" + txMsgSeq.getMessagesCount());
pcs.sendMsg((GeneratedMessage)txMsgSeq.getMessage(i));
if (!syncRxTx) {
Thread.sleep(1000);
}
}
} catch (Exception e) {
}
}
}
class StubRxtask implements Runnable {
public void run() {
while (true) {
try {
// Wait for a message()
TncMessage msg = (TncMessage) pcs.waitMsg(connInt);
System.out.println(msg.toString());
// Add the message to the RX Sequence
rxMsgSeq.addMessage(msg);
System.out.println(rxMsgSeq.getMessagesCount());
if (syncRxTx) {
TncHeader header;
Method invokeGetHeader;
try {
invokeGetHeader = msg.getClass().getMethod("getHeader", null);
header = (TncHeader) invokeGetHeader.invoke(msg, null);
if (header.getType() != EnumMessageType.ACK) {
synchronized (syncObj) {
stopped = true;
syncObj.notify();
}
}
} catch (Exception e) {
System.err.println("ERROR - Impossible to find or invoke getHeader() method on msg");
}
}
stopped = false;
} catch (Exception e) {
}
}
}
}
If it only works fine in debug, this usually happens because of timing issues, which are different in debug mode.
As far as I understand your code, the use of a Phaser would satisfy your requirement. A phaser is like a Barrier: it causes all threads to wait until all threads are waiting on it, except that it is reusable. Since now both threads are waiting till the respective other has arrived, you no longer need your stopped construction nor the synchronized (all is handled by the Phaser internally).
Replace
if (syncRxTx) {
synchronized (syncObj) {
while(!stopped) {
syncObj.wait();
}
}
}
with
if (syncRxTx) {
phaser.arriveAndAwaitAdvance();
}
And
if (header.getType() != EnumMessageType.ACK) {
synchronized (syncObj) {
stopped = true;
syncObj.notify();
}
}
with
if (header.getType() != EnumMessageType.ACK) {
phaser.arriveAndAwaitAdvance();
}
Note: As always with synchronization objects, the Phaser should be declared final.
Use Semaphore for synchronization instead, as these kind of locks handle "early notify".
Semaphore sem = new Semaphore(0);
runConsume() {
.. sem.aquire(1); // will block if nothing avaiable
}
runProduce() {
// receivedMessage
.. sem.release(1);
}
If you use variable in while loop in another thread and want to get fresh data you must declare it with volatile ( Check visibility rule)

Can't stop ExecutorService in java

I have a problem with ExecutorService. I have a button in GUI that calls Runnable class that contains ExecutorService. I tried everything to stop ExecutorService (or main thread) but I didn't find a way to end it. Here is my code. Please post your answers and advises. Best regards.
public void actionPerformed(ActionEvent e) {
final FindGateWaysAndIps scanner = new FindGateWaysAndIps();
if (e.getActionCommand()=="Start Scan"){
scanner.start();
}
if (e.getActionCommand()=="Stop Scan"){
scanner.interrupt();
scanner.stopScans();
}
}
Class "FindGateWaysAndIps"
String ip = "192.168.";
String sql =" ";
static volatile boolean stop = false;
PingResult AllResaults = new PingResult();
int [] AllGateWays = new int [256];
final int NUM_THREADS = Runtime.getRuntime().availableProcessors();
ExecutorService exec = Executors.newFixedThreadPool(NUM_THREADS*5);
public void run() {
stop=true;
while(stop){
for (;GateWayKey<=GateWayKeyStop;GateWayKey++){
if (!stop){
exec.shutdownNow();
Thread.currentThread().interrupt();
break;
}
ip="192.168."+GateWayKey+".1";
AllSQLs.add(exec.submit((new PingTask(ip,GateWayKey,true))));
}
if (!stop) {
exec.shutdownNow();
Thread.currentThread().interrupt();
break;
}
AllGateWays=GetVectorData.GiveMeGateWays();
for (int j=0; j<= AllGateWays.length;j++){
System.out.println("stop je: "+stop);
if (!stop){
exec.shutdownNow();
Thread.currentThread().interrupt();
break;
}
removeDuplicateinVectors();
//System.out.println("Sada je j"+j);
for (;SubNetKey<=SubNetKeyStop;SubNetKey++){
if (!stop){
exec.shutdownNow();
Thread.currentThread().interrupt();
break;
}
ip="192.168."+AllGateWays[j]+"."+SubNetKey;
AllSQLs.add (exec.submit((new PingTask(ip,AllGateWays[j],false))));
}
// Process the result here (this is where you insert into the DB)
//WriteAllDataIntoDataBase();
}
exec.shutdown();
//WriteAllDataIntoDataBase();
}
public void stopScans(){
exec.shutdownNow();
stop=false;
}
Sorry here is PingTask class
public class PingTask implements Callable <String> {
String ips;
String sql;
PingResult PassDataToExternalClass = new PingResult();
//FindGateWaysAndIps DataProccesor = new FindGateWaysAndIps();
int GateWay;
ScanFrame MonitorData = new ScanFrame();
boolean GateWayORSubNet;
int [] AllGateWays = new int [256];
int i=0;
public int[] GiveMeGateWays(){
return AllGateWays;
}
public PingTask (){
}
public PingTask (String ip, int GateWayKey, boolean GateWayORSubNets){
ips=ip;
GateWay=GateWayKey;
GateWayORSubNet=GateWayORSubNets;
}
public String call(){
InetAddress address;
try {
address = InetAddress.getByName(ips);//ako nade gateway neka skoci u petlju u kojoj nade IP adrese pripadajuceg gatewaya
System.out.println("PINGAM: "+ips);
try {
if (address.isReachable(2000)) { //pinga gatewaya s 1000ms (jeli je moguce ovo smanjiti da se ubrza proces)?
System.out.println("Nasa sam IP: "+ips);
AllGateWays[i]=GateWay;
i++;
MonitorData.WriteMonitorData(ips,address.getHostName().toString(),"2000","da");
if (GateWayORSubNet){
sql="REPLACE INTO `gateways` (`ID_GATEWAY` , `GATEWAY_IP` , `GATEWAY_NAME`) VALUES ('"+GateWay+"', '"+ips+"', '"+address.getHostName().toString()+"');";
return sql;
}
else{
sql="REPLACE INTO `subnets` (`IP` , `COMPUTER_NAME` , `GATEWAY_KEY`) VALUES ('"+ips+"', '"+address.getHostName().toString()+"', '"+GateWay+"');";
return sql;
}
} else {
return ";";
}
} catch (IOException e) {
return ";";
}
} catch (UnknownHostException e) {
return ";";
}
}
}
Effectively, in order to get threads stopped, each thread within a pooler inialized by ExecutorService must defined a treatment when this one get interrupted.
This is why daemon starting by:
while(true){
}
isn't suitable and is one of the cause of the impossibility of shutdowning the thread pooler.
Prefer for instance:
while(!Thread.currentThread.isInterrupted){
}
//do here what to do in order to exit and clean safely your job and used resources like open filed.
But even with this, you make wonder what it may not work ......
Avoid to swallow InterruptedException!:
catch(InterruptedException e){
//do nothing
}
Indeed, the interrupted flag is cleared when exception is catched ! So don't forget to set it to true by reinpterrupting the thread:
catch(InterruptedException e){
Thread.currentThread.interrupt();
}
For a more detailed explanation, open this link:
http://www.ibm.com/developerworks/java/library/j-jtp05236/index.html
I guess your PingTask is making URL Connections and connect() call is non interruptible call.
ExecutorService#shutdownNow() offers a way of immediate shutdown by interrupting threads but since these threads can not be interrupted it provides not additional benefit.
It only provides benefit when thread has defined its interruption policy and it performs interruptible operations.
Your problem may be that address.isReachable(...) is not interruptible. Interrupting the thread, like #Mik378 mentioned, sets the interrupt bit on the thread and causes some methods (Thread.sleep(), Object.wait(), and others) to throw InterruptedException. The InetAddress.isReachable(...) will not get interrupted unfortunately.
If you are trying to have your print threads finish immediately so the application can exit, you could make them daemon threads. See here:
Making Callable Threads as Daemon

Categories