How to interrupt this thread? [duplicate] - java

This question already has answers here:
I want my thread to handle interruption, but I can't catch InterruptedException because it is a checked exception
(4 answers)
Closed 8 years ago.
I have the following code:
public class Net {
public static void main(String[] args) {
Runnable task = new Runnable() {
#Override
public void run() {
String host = "http://example.example";
try {
URL url = new URL(host);
StringBuilder builder = new StringBuilder();
HttpURLConnection con = (HttpURLConnection) url.openConnection();
try(BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()))) {
String line;
while (null != (line = in.readLine())) builder.append(line);
}
out.println("data: " + builder.length());
con.disconnect();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
};
Thread thread = new Thread(task);
thread.start();
thread.interrupt();
}
}
This "con.getInputStream()" blocks thread, when host is wrong. How to interrupt this code from another thread?

The general rule is to interrupt uninterruptible threads from 'outside', i.e.
Thread waiting for connection/stream - by closing the connection.
Thread waiting for hang up process to finish - by killing the process.
(not specifically this case) A running long loop - by introducing a boolean variable which is set from outside and checked inside the loop from time to time.

Unfortunately you cannot interrupt the thread which has blocked by some I/O operation(unless you utilize NIO).
you may need to close the stream(by another thread) which reading thread has blocked by.
something like this:
public class Foo implements Runnable{
private InputStream stream;
private int timeOut;
....
public void run(){
Thread.sleep(timeOut);
if(<<ensure the victim thread still is stuck>>){
stream.close();//this will throws an exception to the stuck thread.
}
}
....
}

Set a timeout value with setReadTimeout. Catch the SocketTimeoutException if timeout expires and recover or terminate the program the way you want.

This "con.getInputStream()" blocks thread, when host is wrong. How to interrupt this code from another thread?
This is a FAQ. Interrupting a thread will not cause the readLine(...) method to be interrupted. To quote from my answer here:
I want my thread to handle interruption, but I can't catch InterruptedException because it is a checked exception
It is important to realize that t.interrupt() only sets the interrupted bit in a thread -- it doesn't actually interrupt the thread's processing per se. A thread can be interrupted at any time safely.
So there is no way you can interrupt the thread if it is blocked in readLine(...). You could however change your loop to be something like:
while (!Thread.currentThread().isInterrupted()) {
String line = in.readLine();
if (line == null) {
break;
}
builder.append(line);
}
You can, as others have mentioned, closed the underlying InputStream which will cause the readLine() to throw an Exception.

Related

Using try with resources in multithreaded server in java

I'm reading a book "java networking 4th edition" and in the 9th chapter about server sockets while explaining multithreaded server where each client is handled with the single thread it said the following:
Example 9-3 deliberately does not use try-with-resources for the client sockets accepted by the server
socket. This is because the client socket escapes from the try block into a separate thread.
If you used try-with-resources, the main thread would close the socket as soon as it got
to the end of the while loop, likely before the spawned thread had finished using it.
Here is the Example 9-3
import java.net.*;
import java.io.*;
import java.util.Date;
public class MultithreadedDaytimeServer {
public final static int PORT = 13;
public static void main(String[] args) {
try (ServerSocket server = new ServerSocket(PORT)) {
while (true) {
try {
Socket connection = server.accept();
Thread task = new DaytimeThread(connection);
task.start();
} catch (IOException ex) {}
}
} catch (IOException ex) {
System.err.println("Couldn't start server");
}
}
private static class DaytimeThread extends Thread {
private Socket connection;
DaytimeThread(Socket connection) {
this.connection = connection;
}
#Override
public void run() {
try {
Writer out = new OutputStreamWriter(connection.getOutputStream());
Date now = new Date();
out.write(now.toString() +"\r\n");
out.flush();
} catch (IOException ex) {
System.err.println(ex);
} finally {
try {
connection.close();
} catch (IOException e) {
// ignore;
}
}
}
}
}
I don't really understand why is this happening, why would main thread want to close the socket from the other thread, is it because socket object was created in the main thread and reference was supplied in thread constructor?
What the book is saying is that they chose to do this
try {
Socket connection = server.accept();
Thread task = new DaytimeThread(connection);
task.start();
} catch (IOException ex) {}
instead of
try(Socket connection = server.accept()) {
Thread task = new DaytimeThread(connection);
task.start();
} catch (IOException ex) {}
because when use a try-with-resources block, it closes whatever you put in the parentheses try(...) immediately after it is done. But you do not want this to happen. The connection socket is meant to stay open because it is going to be used in the DaytimeThread that was started.
The main thread doesn't want to close the resource because the spawned thread executes asynchronously.
Within the try, task.start() begins execution of the thread, but it does not wait for it to finish. Therefore, it is possible (even likely) that the main method will reach the end of its try before DaytimeThread.run() finishes.
If the main method's try was a try-with-resources, the connection would be closed at this time. Then, as the DaytimeThread continues to do its work in another thread, it would attempt to use that connection after it is closed.
But to answer your actual question:
why would main thread want to close the socket from the other thread
It's not a socket from another thread. Actually, the main method is accepting the socket connection and then giving it to the DaytimeThread.
Typically, an entity responsible for obtaining a close-able resource should also be responsible for closing it. The simple way to accomplish this is with a try-with-resources. However, this principle cannot be applied with this design because a thread may need the resource after the main thread is done with it.

Setting "flags" between threads in Java

I have a class which connects to a server as below.
#Override
public void run() {
while (running) {
try {
msgHandler.log("Connecting to " + host + ":" + port);
Socket s = new Socket(host, port);
if (s.isConnected() && !s.isClosed()) {
msgHandler.connectionInit(s);
}
BufferedInputStream input = new BufferedInputStream(s.getInputStream());
}
}
The consumer which is the msgHandler, frequently polls the socket if a connection ever goes down as below.
#Override
public void connectionInit(Socket s) throws IOException {
logger.info("Connected to AWW Service on " + configuration.getAwwHost() + ":" + configuration.getAwwPort());
output = new BufferedOutputStream(s.getOutputStream());
connector.componentReady();
Timer t = new Timer();
t.schedule(new TimerTask() {
#Override
public void run() {
try {
pollServer();
} catch (IOException e) {
// SOCKET GETS BROKEN HERE
}
}
}, 0, 25000);
}
Question is, how can i communicate from the exception i get when the socket connection gets broken back to the run() thread, so it can try to reinitialize the socket and the input stream?
I dont think a notify() or wait() mechanism is appropriate here as wait() will just put the run() thread to sleep.
I was thinking whats the equivalent of setting a flag when the connection gets broken, and the run() thread constantly checks the flag, and when it is set to true, it reinitialize the socket. But i am sure there would be a more efficient multi threading approach native to java for achieving this.
I think the simplest approach is using an AtomicBoolean variable that is accessible to both threads - you could pass the variable in when constructing each thread's run class if necessary. Nice thing about AtomicBoolean is that it is already thread safe/synchronized and mutable so that it can be passed around and modified by reference.
See this similar question for some more details.
I think that in the run() function, you should have a code like the following one.
// ...
try
{
// ...
int read = input.read(...);
// ...
}
catch (IOException e)
{
// TODO: terminate the thread and restart a new connection
}
So, if an error occurs during the pollServer() call, also my code above should generate an exception.
Also when you call the close function of a Socket object, the input and output streams will generate the relative exceptions.

How to terminate a thread blocking on socket connect

In my android app, my activity is starting another thread for some socket network operations, and this thread is always waiting for incoming data from the socket(blocking on read() function in a while loop).
Now, when my activity gets destroyed, I would like to keep things clean, and destroy that thread. To implement this functionality, I defined a volatile boolean variable isSupposedToStop which would be initialized to false, and when onStop() gets called, it sets that boolean to true, and calls socket.shutdownInput() which causes the thread blocking on read() to throw an IOException, then read the isSupposedToStop boolean to know that it is supposed to stop.(if you have better ways feel free to discuss it).
So, in my run() implementation after connecting my socket I have:
sock= new Socket("127.0.0.1", 1234);
InputStream is= sock.getInputStream();
byte[] buffer= new byte[200];
while(true){
if(isSupposedToStop) return;
try {
is.read(msgSizeBuff, 0, 200);
} catch(IOException e){
}
if(isSupposedToStop) return;
//do something with the received message
}
in onStop(), I have:
isSupposedToStop= true;
if(sock!= null) {
try {
sock.shutdownInput();
sock.close();
} catch (IOException e) {
}
}
thread.join()
that is working good. as when the thread is waiting for new data (blocking on read()), read() throws an IOException immediately when onStop() calls shutdownInput(), and control is back to the thread which reads my boolean value and exits.
but the problem is happening if onStop() gets called when the thread is still waiting to establish the connection (blocking on new Socket()) so if the host is down for example the app freezes for about 3 seconds, so do you recommend to just omit the thread.join() call? or is there a way to wake up this thread?
Once you have called the read method you are essentially blocked - you can only escape by interrupting the thread.
public void test() {
Thread socketThread = new Thread(new Runnable() {
#Override
public void run() {
System.out.println("Hello");
}
});
// Do your stuff.
//...
// Time to quit - should abort any blocked reads.
socketThread.interrupt();
}
Another alternative - this may not work at all - is to use the available method of InputStream.
public void test() throws IOException {
Socket sock = new Socket("127.0.0.1", 1234);
InputStream is = sock.getInputStream();
boolean done = false;
while (!done) {
int available;
if ((available = is.available()) > 0) {
// Your read stuff.
is.read(buffer, 0, available);
}
}
}
The new Socket isn't supposed to block networking. Not even a SYN/ACK.
Therefore you can setSOTimeout() right after construction. But you wouldn't set it to anything less than 3 seconds to be fair.
You are suggesting that it takes 3 seconds to respond to a socket.close()... So I fear it cannot get any faster, but you can try a thread.interrupt(), in case it is sitting in interruptable (non native) code.

Perform an action after interrupting a thread

I have two threads, threadOne waits for user input, threadTwo interrupts it with an interrupt() method before user input is received .
I would like to execute a block of code upon successful interruption of threadOne. I tried doing that by catching a ClosedByInterruptException within threadOne's run() method, but the compiler gives the following error:
exception ClosedByInterruptException has already been caught.
Here's the code:
class InputInterruption {
public static void main(String[] args) {
final Thread t2 = new Thread() {
public void run() {
try {
System.out.print("make a selection: ");
String userInput = (new BufferedReader(new InputStreamReader(System.in))).readLine();
System.out.println(String.format("user input: %s", userInput));
} catch (IOException e) {
System.out.println("Oops..somethign went wrong.");
System.exit(1);
} catch(ClosedByInterruptException e) {
System.out.println("Successfully interrupted");
}
}
};
t2.start();
Thread t1 = new Thread() {
public void run() {
try {
sleep(1000);
System.out.println("interrupting InputStreamReader");
t2.interrupt();
System.exit(0);
} catch (InterruptedException e) {
System.out.println("Successfully interrupted");
}
}
};
t1.start();
}
}
ClosedByInterruptionException extends IOException. Try switching the order of your catch statements.
ClosedByInterruptException is a subclass of IOException so your first catch block intercepts all IOException instances including ClosedByInterruptException.
Change the order of catch blocks and you are good.
To wait for a thread to complete, you could use Thread.join(). Change your t1 code to the following:
....
t2.interrupt();
t2.join();
....
Disclaimer: I haven't tried this code myself.
ClosedByInterruptException is actually sub class of IOException. So even if the try block throws ClosedByInterruptException it will be caught by the first catch block with statement:
catch (IOException e). Change the order and you should be good to go.
I tried doing that by catching a ClosedByInterruptException within threadOne's run() method...
Other's have solved the exception compilation error but I do not see any methods that actually throw ClosedByInterruptException so I'm surprised your code compiles. Your code does not compile for me in Eclipse for that reason. Maybe your IDE is not making the unthrown exception an error -- I'd recommend turning on that error/warning. ClosedByInterruptException is only thrown by certain NIO channels that implement InterruptibleChannel.
If you are reading from a normal stream, the only way to stop the thread from reading is to close the underlying stream. In this case you could try to close System.in but that may not actually stop the thread from reading unfortunately. On OS X, closing System.in causes the readLine() method to return null in the reader thread. You then can continue and execute some sort of code block as necessary.
sleep(1000);
System.out.println("closing InputStreamReader");
System.in.close();
Then you can do:
String userInput =
new BufferedReader(new InputStreamReader(System.in)).readLine();
if (userInput == null) {
// stream was closed, do something special
...
Btw, in the interrupting code you have:
try {
sleep(1000);
t2.interrupt();
} catch (InterruptedException e) {
System.out.println("Successfully interrupted");
}
The output message there is misleading. If sleep(...) throws a InterruptedException then it was the thread that was sleeping that was interrupted. It has nothing to do with the t2.interrupt() call. Just FYI.

Server Socket - Sending a test message to detect connection

I'm trying to use server sockets to set up a connection between a client and a server. I'm also not using java.nio.
The problem is that I'm constantly sending a test message, and detecting whether if it is successful in sending the message (the client is still connected), if not, then the client is disconnected.
Shown here:
try
{
Scanner in = new Scanner(socket.getInputStream());
BufferedReader in_2 = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while(stopThread)
{
if(in_2.ready())
{
String message = in_2.readLine();
dt = new DateTime();
PrintStream out = new PrintStream(socket.getOutputStream());
server.detect(message, dataSets, out);
dataSets.add(message);
GUI.textArea_1.append(message + "\r\n");
GUI.textArea_1.setCaretPosition(GUI.textArea_1.getDocument().getLength());
}
else
{
PrintStream out = new PrintStream(socket.getOutputStream());
out.println("Testing Connection \r\n");
if(out.checkError())
{
try
{
socket.close();
}
catch (IOException e)
{
e.printStackTrace();
}
stopThread = false;
GUI.textArea.append(userName + " disconnected \r\n");
GUI.textArea.setCaretPosition(GUI.textArea.getDocument().getLength());
server.inputDataForm(userName, dt, dataSets);
}
Thread.sleep(3000);
}
}
The problem is that the Thread.sleep(3000) is actually interfering with getting data, since after 3 seconds, I will get a huge amount of data (because I stopped the thread for 3 seconds).
Now, what I proposed is a anonymous class in the else statement.
class runThread implements runnable
{
void run()
{
//Put the else statement here
}
}
But the stopThread = false is not a constant, which I'm trying to control.
Other threads I've searched only puts variables inside main inside the anonymous class, but I need stopThread to stop the while loop if the client is disconnected.
Does anyone have an idea?
Thanks!
Consider setting a short timeout on your socket. This will allow you to control how long your thread will block while waiting for data from the socket.
If data are not quickly available, a very specific java.net.SocketTimeoutException will be raised. You can handle this exception by checking your stopThread flag. If it is set, you can return from the method. Otherwise, the socket is still valid and you can try another read operation with timeout.
If any other exception type is thrown, your socket is probably no longer valid.
socket.setSoTimeout(20); /* 1/50th of a second. */
BufferedReader in = new BufferedReader
(new InputStreamReader(socket.getInputStream(), StandardCharsets.UTF_8));
while (!stop) {
try {
String message = in.readLine();
if (message == null)
handleEOF();
else
handleMessage(message);
} catch(SocketTimeoutException ignore) {
/* Loop back to check "stop" flag. */
continue;
} catch(IOException ex) {
handleDisconnection();
break;
}
}
By the way, if you are using Swing, remember that you can only modify graphical components from Swing's Event Dispatch Thread, and you can't tie up the EDT in long-running operations like this socket handling. You should be passing tasks from this thread to Swing's invokeLater() utility.
Why don't you make a class that implements runnable but also has the method stop();
public class MyRunner implements Runnable(){
MutableBoolean stop = false;
public void run(){...}
public void stop(){
stop = true;
}
}

Categories