Thursday, June 08, 2006

Non Blocking with Traditional Java IO - On the Use of InputStream.available() and Thread.sleep()

Some time ago I did quite a lot of IO in Java and I yet did not see this way of reading a InputStream from a Socket:
    InputStream in=channel.getInputStream();

    channel.connect();

    byte[] tmp=new byte[1024];
    while(true){
      while(in.available()>0){
        int i=in.read(tmp, 0, 1024);
        if(i<0)break;
        System.out.print(new String(tmp, 0, i));
      }
      if(channel.isClosed()){
        System.out.println("exit-status: "+channel.getExitStatus());
        break;
      }
      try{Thread.sleep(1000);}catch(Exception ee){}
    }
    channel.disconnect();


This comes from a piece of code from an example of JSch , a good ssh client in java. A work collegue had the bad idea to remove the Thread.sleep call and was struggling with why it would randomly work.The way I would have done it is the following:
    InputStream in=channel.getInputStream();

    channel.connect();

    byte[] tmp=new byte[1024];
    int bytesRead = 0;
    while((bytesRead = in.read(tmp,0,1024) >= 0){
      System.out.print(new String(tmp, 0, bytesRead));
    }

    if(channel.isClosed()){
      System.out.println("exit-status: "+channel.getExitStatus());
      break;
    }
    channel.disconnect();


This has the advantage of being more readable and having less secret spices in it. In the first code, the call to available() is non blocking, meaning that without the Thread.sleep(), there will never be the time for the socket buffer to fill up. But is the first code more efficient or the second code?

I did a search on google to understand the interest of the first code. The only advantages I found in the first code are the possibility to interrupt the thread running the code and a finer grained control on timeouts.

There is a lengthy explanation by Doug Lea in his book "Concurrent Programming in Java". This book usually provides excellent explanations, and is a must read for anybody doing concurrent programming. But this time, about this subject, I did not find him that clear.

There is a more simple explanation in a course from San Diego State University (see last example)
A read() on an inputstream or reader blocks. Once a thread calls read() it will not respond to interrupt() (or much else) until the read is completed. This is a problem when a read could take a long time: reading from a socket or the keyboard. If the input is not forth coming, the read() could block forever.

As usual, you should not rely on all what you read on the web, as this page (SCJP Questions & Answers) testifies:
Q. When will a Thread I/O blocked?
A:
When a thread executes a read() call on an InputStream, if no byte is available. The calling Thread blocks, in other words, stops executing until a byte is available or the Thread is interrupted.

Still I am wondering if the second code would not just go into IOException (socket timeout), on timeout (adjustable with Socket.setTimeout ) and release the Thread then. Do you have an idea when the first code could be better?

Non Blocking with Traditional Java IO - On the Use of InputStream.available() and Thread.sleep()

Some time ago I did quite a lot of IO in Java and I yet did not see this way of reading a InputStream from a Socket:
    InputStream in=channel.getInputStream();

    channel.connect();

    byte[] tmp=new byte[1024];
    while(true){
      while(in.available()>0){
        int i=in.read(tmp, 0, 1024);
        if(i<0)break;
        System.out.print(new String(tmp, 0, i));
      }
      if(channel.isClosed()){
        System.out.println("exit-status: "+channel.getExitStatus());
        break;
      }
      try{Thread.sleep(1000);}catch(Exception ee){}
    }
    channel.disconnect();


This comes from a piece of code from an example of JSch , a good ssh client in java. A work collegue had the bad idea to remove the Thread.sleep call and was struggling with why it would randomly work.The way I would have done it is the following:
    InputStream in=channel.getInputStream();

    channel.connect();

    byte[] tmp=new byte[1024];
    int bytesRead = 0;
    while((bytesRead = in.read(tmp,0,1024) >= 0){
      System.out.print(new String(tmp, 0, bytesRead));
    }

    if(channel.isClosed()){
      System.out.println("exit-status: "+channel.getExitStatus());
      break;
    }
    channel.disconnect();


This has the advantage of being more readable and having less secret spices in it. In the first code, the call to available() is non blocking, meaning that without the Thread.sleep(), there will never be the time for the socket buffer to fill up. But is the first code more efficient or the second code?

I did a search on google to understand the interest of the first code. The only advantages I found in the first code are the possibility to interrupt the thread running the code and a finer grained control on timeouts.

There is a lengthy explanation by Doug Lea in his book "Concurrent Programming in Java". This book usually provides excellent explanations, and is a must read for anybody doing concurrent programming. But this time, about this subject, I did not find him that clear.

There is a more simple explanation in a course from San Diego State University (see last example)
A read() on an inputstream or reader blocks. Once a thread calls read() it will not respond to interrupt() (or much else) until the read is completed. This is a problem when a read could take a long time: reading from a socket or the keyboard. If the input is not forth coming, the read() could block forever.

As usual, you should not rely on all what you read on the web, as this page (SCJP Questions & Answers) testifies:
Q. When will a Thread I/O blocked?
A:
When a thread executes a read() call on an InputStream, if no byte is available. The calling Thread blocks, in other words, stops executing until a byte is available or the Thread is interrupted.

Still I am wondering if the second code would not just go into IOException (socket timeout), on timeout (adjustable with Socket.setTimeout ) and release the Thread then. Do you have an idea when the first code could be better?

Monday, June 05, 2006

Top 10 Most Read Last Week On Javablogs.com, Week 22


Most read last week

  1. Why I'm leaving Sun and... what next? (304): Leaving Sun is possibly one of the most difficult decisions I've ever made. But I think it's time for me to start new things and, well, it's also time for Sun to start new things. [read]

  2. 9 new and *noteworthy* features in Eclipse 3.2 (280): Chris Laffra has put a big presentation of all the new and noteworthy features that are coming in the Eclipse 3.2 platform.There is lots of screenshots, [read]

  3. Don’t you just love it when Microsoft is forced to use Java? (253): Don’t you just love it when Microsoft is forced to use Java? [read]

  4. Joshua Bloch Shocking Confession: java.util.Arrays Is Broken (218): (This should be all over the net by now. I first saw it here. [read]

  5. Signs You're a Crappy Programmer (and don't know it) (212): This ought to put a smile on your face unless it hits too close to home! [read]

  6. Spring starts you programming in pure XML! (211): I'm now very enthusiastic, some may say obsessed, about using the Spring Framework. Spring is certainly making me more productive. [read]

  7. Google's GWT Example: Interactive FIFA 2006 World Cup Application (203): Goto the application without reading the entry.A couple of weeks ago google released the Google Web Toolkit. The toolkit lets Java developers create AJAX application, [read]

  8. Testicular Cancer (198): I've just been diagnosed with testicular cancer. It's probably seminoma (which is relatively good). However, other things are now on my mind and so this blog will not be updated for a while. [read]

  9. Intel iMac - the best Java development box in the world (182): Cancelling my MacBook Pro order worked out really well for me. Firstly, I'm getting a new company laptop (a big grey Dull), and the prospect of carrying two laptops around just scares me. Second, [read]


Most read last week-end

  1. Joshua Bloch Shocking Confession: java.util.Arrays Is Broken (218): (This should be all over the net by now. I first saw it here. [read]

  2. Hibernate3, Annotations & Spring: the morning after (116): Ok, after fiddling with a few more jars, I seem to have gotten past my main obsticle. Now I'm back to the "common problems" phase of working with Hibernate. Still evaluating, [read]

  3. JBoss Seam: Make Spring inside (111): We here try out JBoss Seam, and find JBoss Microkernel, is this a IOC from JBoss? Why dont we use Spring instead? [read]

  4. Why are we still dealing with C++ vs Java (97): I had an interesting conversation this week with someone that believed that the Java world was filled with people who couldn’t code. In his opinion, [read]

  5. "Look Ma, no locks!" (97): Brian Goetz has written an excellent introductory article on nonblocking algorithms and showcases some simple nonblocking data structures with code examples and pictures. [read]

  6. 6 Ways of Setting Java Classpath (96): How to set Java classpath? List as many ways as you can. This can be an interesting Java job interview question. [read]

  7. Spring, JBoss and The Elephant (96): Interface 21 and BEA recently announced the release of Pitchfork, the EJB3 implementation within the Weblogic container, built using Spring. [read]

  8. Ubuntu 6.06 (94): I upgraded my Ubuntu box the other night. The process was pretty impressive. For one thing, it was significantly faster than an MSWindows or MacOS upgrade. [read]

  9. Integrating spring and GWT (84): I just completed my first shot at integrating Spring with GWT. You can check it out here Here’s what you do to expose a simple service. 1) Write the remote service, [read]