Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I timeout a function that blocks in Java?

Basically, I'm calling BufferedReader.ReadLine(); However I'm in a multithreaded server, where I'm synchronizing a node in a tree. So when this ReadLine function is called, if someone else reaches the node, they're locked out. I can't figure out how to make a timelimit on the amount of time ReadLine waits for a response before quitting the thread. The closest I got was to create a new thread that would sleep for 1ms then check to see if the variable that I set ReadLine to is changed. So something like this:

synchronized (pointer) {
    String answer = "";
    Thread d = new Thread(new Runnable() {
        public void run() {
            try {
                int i = 0;
                while (answer.equals("")) {
                    if (i == 10000) {
                        System.out.println("Timeout Occured");
                        System.exit(0);
                    }
                    try {
                        Thread.sleep(1);
                        i++;
                    }
                    catch(Exception e) {
                        System.out.println("sleep problem occured");
                    }
                }
            }
            catch (IOException ex) {
            }
        }    
    });

    d.start();
    answer = socketIn.readLine();
}

This did what I wanted it to, but I couldn't figure out how to stop the current thread to unlock the node so other users could continue instead of killing the whole server. Finally, I thought maybe I could do this:

    Thread d = new Thread(new Runnable() {
        public void run() {
            try {
                answer = socketIn.readLine(); 
            } catch (IOException ex) {
            }
        }    
    });

    d.join(10000);
    catch (InterruptedException e){
    socketOut.println("Timeout Occured. Returning you to the beginning...");
    socketOut.flush();
    return;
}

But this still seems to block and not be able to continue. Could someone help me out with this? I can't understand what I'm doing wrong?

I also tried to get the ExecutorService to work, but couldn't. Is this my answer? How would I implement it?

[EDIT] socketIn is a BufferedReader, should have said that explicitly sorry. Also, the client is connecting via telnet, though I don't think that matters.

What I'm doing here is a "celebrity guessing game" where users can add celebrities to the tree. So I need to lock the node that the person is editing for thread-safety

like image 580
Jeff Avatar asked Aug 15 '26 01:08

Jeff


1 Answers

Is this homework? It's suspiciously close to a question asked by someone else yesterday. If so it should have the homework tag.

You only need to lock on something when a thread will modify data that other threads may read/modify.

If you're locking something waiting on input, the scope of your lock is far too broad.

Your flow should be:

  • read input from client (blocking readLine())
  • lock shared resource
  • modify
  • unlock

(This is assuming you've got one thread per connection/client, and are blocking on the read from the client)

That being said ... if you're reading from a socket and want it to time out, you need to use clientSocket.setSoTimeout(1000); when you first accept the connection. If your BufferedReader is waiting for that amount of time (in milliseconds) and doesn't get input, it will throw a java.net.SocketTimeoutException

String inputLine = null;
try 
{
    inputLine = in.readLine();
    if (inputLine == null)
    {
        System.out.println("Client Disconnected!");
    }
    else 
    {
        // I have input, do something with it
    }
}
catch(java.net.SocketTimeoutException e)
{
    System.out.println("Timed out trying to read from socket");
}
like image 52
Brian Roach Avatar answered Aug 17 '26 16:08

Brian Roach



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!