Solved

timing out a method

Posted on 2002-03-17
29
674 Views
Last Modified: 2007-11-27
hi,

I have a method, that gets a website as a String. Sometimes this method hangs, so i want to construct a timeout.
So if I call the method and it doesn't deliver the page within x seconds the program shall abort the download and continue its work.

this is a general problem, so an improved download method will help me, but won't fix the abstract problem itself...

So: how can I timeout a method-call ?

Ben Utzer

0
Comment
Question by:benutzername
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 12
  • 12
  • 3
  • +1
29 Comments
 
LVL 92

Expert Comment

by:objects
ID: 6875714
You can't really timeout a method.
Sounds like what you want to do is is instead implement a timeout on your comms. Have a look at setSoTimeout() method in Socket class.
0
 
LVL 5

Expert Comment

by:LexZEUS
ID: 6876081
Apart from objects sugestion, maybe you can play with this code.. but I don't have idea this will work or not..

public class Something
{
...
  public void do readFromSocket()
  {
    TimerThread = new TimerThread(Thread.currentThread(),1000);
    try
      {
      mySocket.getInpuStream().read(buffer);
      }
    catch (Exception ex)
      {
      System.out.println("I/O error or unable to read from socket in 1 second");
      }
  }
...
}

public class TimerThread extends Thread
{
  Thread td;
  int waitTime;
  TimerThread(Thread t, int time)
  {
    td = t;
    waitTime = time;
    start();
  }

  public void run()
  {
  try {
      sleep(time);
      td.interrupt();
      }
  catch (Exception ex) { }
  }
}

Basically, the idea is to interrupt read(buffer) in 1000msec (1 sec).
Will this work? I dunno .. coz' I myself never try..

Alex
0
 
LVL 92

Expert Comment

by:objects
ID: 6876090
I don't think you can interrupt a blocked read so I don't think that'll work, but setting the socket timeout will have basically the same effect.
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

Author Comment

by:benutzername
ID: 6876213
interrupt only sets the interrupt flag - you can read this flag with isInterrupted() - so it doesn`t really interrupt anything. the socket timeout will help me for the special problem of the connection, but the abstract problem still exists: how to kill a thread ?

imagine, you have a multithreading program, that has to run for weeks without crashing. you want to build a supervisor that scans all running threads from time to time. if one of the threads crashed, the supervisor will delete the thread and start a new thread to replace the crashed one - thats what i have to work out.

it seems, that sometimes the garbage collection doesn't work like it should, because sometimes a thread is kicked out by java, because of low memory, even if there would be enough memory if java just did some more garbage collection :(
0
 

Author Comment

by:benutzername
ID: 6876257
I found a soloution myself in between:

public class Test implements Runnable {

   public long lastActionPerformed;

   public Test() {
       start();
   }

   public void run() {
       while(true) {
           lastActionPerformed = System.currentMillis();
           // now do something
           // ....
       }
   }  
}


The thread t will be supervised by another thread. The other thread will check lastActionPerformed from time to time - if last action is too long ago (over 5000ms), it will delete the thread through Thread.join(whenToJoin) and construct a new one as replacement.

public class Supervisor implements Runnable {

   private Thread t;

   public static void main (String args[]) {
       Thread s = new Thread(new Supervisor());
   }

   public Supervisor() {
       t = new Thread(new Test());
       start();
   }

   public void run() {
       while(true) {          
           if ( System.currentMillis() - t.lastActionPerformed > 5000 ) {
                 t.join(1);
                 t = new Thread(new Test());      
           }
       }
   }  
}

...hope this will work, didn't check the syntax in java - but the concept will work.
0
 
LVL 92

Expert Comment

by:objects
ID: 6876259
> interrupt only sets the interrupt flag

In the general case, interrupt() will cause the thread to throw an InterruptedException so it can be used to break a thread.

> if one of the threads crashed

If a thread is crashed then it is no longer running.
You just need to start a new one.
0
 
LVL 92

Expert Comment

by:objects
ID: 6876263
Just call isAlive() if you want to know if a thread is still running.
0
 
LVL 92

Expert Comment

by:objects
ID: 6876315
Your example won't work. join() doesn't delete the thread, it just waits for it to finish.
0
 
LVL 92

Expert Comment

by:objects
ID: 6876321
The only way I can think of to 'timeout' a method is thru the use of interrupt().
0
 

Author Comment

by:benutzername
ID: 6876363
API about join(long milliseconds): "Waits at most millis milliseconds for this thread to die."

What happens, if the thread doesn't die within the timerange of "milliseconds" ?

isAlive won't help me either - the thread is not "crashed" in the sense of "passed off" but "crashed" in the sense of "hanging in some point without continueing its work".

I find hanging threads by checking their lastActionPerformed variable.

It's a pitty, that sun didn't implement Thread.destroy() yet...
0
 

Author Comment

by:benutzername
ID: 6876365
I will try it with a combination of interrupt() and setSoTimeout()...
0
 
LVL 92

Expert Comment

by:objects
ID: 6878218
> What happens, if the thread doesn't die within the timerange of "milliseconds" ?

Then the join method simply returns.

> "hanging in some point without continueing its work".

Threads hang for a variety of well defined reasons such as blocking I/O, sleep, wait etc.
Most of these can be awoken by an interrupt().

> I find hanging threads by checking their lastActionPerformed variable.

Yes, but then how do you stop them.

> It's a pitty, that sun didn't implement Thread.destroy() yet...

You can stop a thread, but it's prone to deadlocks and is not recomended.
0
 

Author Comment

by:benutzername
ID: 6881472
>In the general case, interrupt() will cause the thread to throw an InterruptedException so it can be
used to break a thread.

Where do I have to put the try-catch to catch the InterruptedException ? I tried it everywhere, but I don't find out, where to catch it :(


best regards,

Ben Utzer
0
 
LVL 92

Expert Comment

by:objects
ID: 6881485
In the thread you are interrupting.

public void run()
{
   try
   {
      dostuff();
   }
   catch (InterruptedException ex)
   {
      // Someones interrupted me
   }
}
0
 
LVL 5

Expert Comment

by:LexZEUS
ID: 6881574
I thought interrupt() only interrupt when a thread in sleep() or wait() condition, it doesn't interrupt a thread which is not in one of above condition?
0
 
LVL 92

Expert Comment

by:objects
ID: 6881585
That is correct. I thought we were dealing with blocked threads.
If the thread is executing there is no (safe) way to stop it. If this is required then the thread should provide a mechanism for halting itself.
0
 
LVL 5

Expert Comment

by:LexZEUS
ID: 6881696
yes I agree.. The thread itself should implements some mechanism to exit from run() method for garbage collection.

....
public boolean forcedToStop = false;
public void run()
{
  while(!forcedToStop)
    {
    if (!forcedToStop) doSomethingPartOne();
    if (!forcedToStop) doSomethingPartTwo();
    if (!forcedToStop) doSomethingPartThree();
    if (!forcedToStop) doSomethingPartAndSoOn();

    // give another thread chance to execute
    if (!forcedToStop)
       try {sleep(100);} catch (Exception ex) { }
    }  
}
....

To stop the thread:

if (myThread.isAlive())
    {
    myThread.forcedToStop = true;
    myThread.interrupt();
    myThread=null; // for further garbage collection
    }

The only way to stop thread instantly (but not recommended) is using _yourThread_.stop() method...
0
 

Author Comment

by:benutzername
ID: 6882181
i have no luck :( it seems that the exception is already catched within suns code, so it doesn't get down to my code and a can't catch and process it.

My classes are "Download" and "DownloadThread". Download starts a DownloadThread and gives it an URL. If DownloadThread hasn't completed after x seconds, it will be interrupted. But the exception is caught by something called "AWT blocker activation" ... whatever that is:

AWT blocker activation interrupted:
java.lang.InterruptedException
        at java.lang.Object.wait(Native Method)
        at java.lang.Object.wait(Object.java:426)
        at sun.awt.AWTAutoShutdown.activateBlockerThread(AWTAutoShutdown.java:309)
        at sun.awt.AWTAutoShutdown.notifyThreadBusy(AWTAutoShutdown.java:146)
        at java.awt.EventQueue.initDispatchThread(EventQueue.java:654)
        at java.awt.EventQueue.postEvent(EventQueue.java:209)
        at java.awt.EventQueue.postEventPrivate(EventQueue.java:190)
        at java.awt.EventQueue.postEvent(EventQueue.java:164)
        at java.awt.EventQueue.invokeLater(EventQueue.java:757)
        at javax.swing.SwingUtilities.invokeLater(SwingUtilities.java:1142)
        at javax.swing.text.StyleContext.reclaim(StyleContext.java:431)
        at javax.swing.text.StyleContext.addAttribute(StyleContext.java:274)
        at javax.swing.text.html.StyleSheet.addAttribute(StyleSheet.java:541)
        at javax.swing.text.StyleContext$NamedStyle.addAttribute(StyleContext.java:1490)
        at javax.swing.text.StyleContext.addStyle(StyleContext.java:89)
        at javax.swing.text.html.StyleSheet.addRule(StyleSheet.java:978)
        at javax.swing.text.html.StyleSheet$CssParser.endRule(StyleSheet.java:3097)
        at javax.swing.text.html.CSSParser.parseRuleSet(CSSParser.java:256)
        at javax.swing.text.html.CSSParser.getNextStatement(CSSParser.java:161)
        at javax.swing.text.html.CSSParser.parse(CSSParser.java:136)
        at javax.swing.text.html.StyleSheet$CssParser.parse(StyleSheet.java:3005)
        at javax.swing.text.html.StyleSheet.loadRules(StyleSheet.java:303)
        at javax.swing.text.html.HTMLEditorKit.getStyleSheet(HTMLEditorKit.java:358)
        at javax.swing.text.html.HTMLEditorKit.createDefaultDocument(HTMLEditorKit.java:185)
        at javax.swing.JEditorPane.setEditorKit(JEditorPane.java:945)
        at javax.swing.JEditorPane.setContentType(JEditorPane.java:871)
        at javax.swing.JEditorPane.getStream(JEditorPane.java:696)
        at nkUtil.www.DownloadThread.downloadWWWPage(DownloadThread.java:73)
        at nkUtil.www.DownloadThread.run(DownloadThread.java:46)
        at java.lang.Thread.run(Thread.java:536)
0
 

Author Comment

by:benutzername
ID: 6882183
You might wonder, what JEditorPane has to to with my DownloadThread - it's like that:

I tried many different code samples for retrieving a web page over http, but most of them were refused by some servers, because they didn't know how to identify correctly.

JEditorPane is able to deliver an InputStream to download a HTML-Document and is not refused by any server, whoever.

Ben Utzer
0
 

Author Comment

by:benutzername
ID: 6882195
This is the source, I'm struggling with:

import java.net.URL;

public class Download {

    /** Creates new Download */
    public Download() {
    }
   
    //--------------------------------------------------------------------------
    // Interface
   
    public String downloadToString(URL url, long timeout) {
        try {
            long startTime = System.currentTimeMillis();
            DownloadThread d = new DownloadThread(url);
            Thread t = new Thread(d);
            t.start();
            while(d.getResult() == null) {
                if ((System.currentTimeMillis() - startTime) > timeout) {
                    t.interrupt();
                    break;
                } else {
                    try{ wait(100);} catch(Exception e) {}                
                }
            }
            return d.getResult();
        } catch (Exception e) {
            System.out.println("downloadToStringException: " + e);
            return null;
        }
    }

}


---------------------------------------------------------

import java.net.*;
import java.io.*;
import javax.swing.JEditorPane;

class DownloadThread extends JEditorPane implements Runnable
{
   
    //--------------------------------------------------------------------------
    // Felder
   
    // read buffer size
    private static int READ_BLOCK_SIZE = 128;
    private char[] inputBuffer = new char[READ_BLOCK_SIZE];
    private int charsRead;    
   
    //
    private URL url;
    private String result = null;
   
    //--------------------------------------------------------------------------
    // Konstruktor
   
    public DownloadThread(URL url) {    
        this.url = url;
    }

    //--------------------------------------------------------------------------
    // runtime
   
    public void run() {
        result = downloadWWWPage(url);
    }    
   
    //--------------------------------------------------------------------------
    // Interface
   
    public String getResult() {
        return result;
    }

   
    //--------------------------------------------------------------------------
    // Download
   
    private String downloadWWWPage(URL url) {
        StringBuffer result = new StringBuffer();
        InputStreamReader in = new InputStreamReader(getStream(url));          
        while(true) {
            charsRead = in.read(inputBuffer, 0, READ_BLOCK_SIZE);
            if (charsRead == -1) {                    
                break;
            } else {
                result.append(inputBuffer, 0, charsRead);
            }                
        }
        // result
        return result.toString();
    }    
}

-----------------------------------------------------------

It's the best working web-document download routine I found yet, but it still has this interruption problem.

I'm building a spider, so I will need the best web-document download routine available, I gotta work hard on that issue.

Ben Utzer
0
 

Author Comment

by:benutzername
ID: 6882207
ooopps, there was an error in the downloadWWWPage() - here is an update:
---------------------

    private String downloadWWWPage(URL url) {
        try {
            StringBuffer result = new StringBuffer();
            InputStreamReader in = new InputStreamReader(getStream(url));          
            while(true) {
                charsRead = in.read(inputBuffer, 0, READ_BLOCK_SIZE);
                if (charsRead == -1) {                    
                    break;
                } else {
                    result.append(inputBuffer, 0, charsRead);
                }                
            }
            // result
            return result.toString();
        } catch (Exception e) {
            return "";
        }            
    }    
0
 
LVL 92

Expert Comment

by:objects
ID: 6884081
The actual connection to the server appears to be being handled in a seperate thread ie. not the one your interrupting. I'd say the thread you are interrupting is in fact just waiting on the connection to complete.
Also worth mentioning that you cannot interrupt blocked I/O.
0
 
LVL 1

Expert Comment

by:saurav17
ID: 6888032
Hi benutzername,


Your problem is lying inside downloadwwwpage(url).


pass ur timeout value to this method. inside ur while validate ur timeout time. if u exceed the specified time come out of while loop, then ur download gets aborted.



Regards,
K.J.S.
0
 

Author Comment

by:benutzername
ID: 6888353
sorry, that doesn't work, because sometimes it takes hours to receive one block (to finish one loop) - in what case I would like to interrupt and cancel the transfer.
0
 
LVL 1

Expert Comment

by:saurav17
ID: 6888536
hi benutzername,

now I'm totally lost.
when u r not sure of the length of the process why do u want to give timeout.

Pls., clear me where do u need timeout here and for what purpose. So, that I may help u out.


Regards,
K.J.S.
0
 

Author Comment

by:benutzername
ID: 6889176
ok, I will describe my situation in detail:

I'm programming a webcrawler. I start with a given URL (let's say "http://directory.google.com/"), download the HTML-Document, search the HTML-Source for any hyperlinks and store all the links into a database.

Then I get the next URL from the database, download it, write all links into the database and so on...

It happens, that a URL doesn't work correctly, in which case my webcrawler "hangs". For example, some servers just stop sending data, so that the line

charsRead = in.read(inputBuffer, 0, READ_BLOCK_SIZE);
               
will take forever.

I need a VERY robust download algorhithm, that doesn't hang on bad servers. It should time out after let's say 30 seconds, just forget the current download and continue with the next URL.

If anyone needs my webcrawler code, I have no problem with sharing it, its an noncommercial research project. The crawler works very good and is quite elaborate now (except for the download thread...). So if somebody else is working on a crawler, too, we could exchange our code.
0
 
LVL 92

Accepted Solution

by:
objects earned 200 total points
ID: 6889754
If you want to control the timeout then
1. you can't use JEditorPane's getStream() method, as you need control over making the connection.
2. you can't use URLConnection either as this does not allow you to specify the timeout.

Have a look at HTTPClient at http://www.innovation.ch/java/HTTPClient/
It provides far better control over your download.
0
 

Author Comment

by:benutzername
ID: 6890215
that's what i needed ! thanks a lot for that tip :)
0
 
LVL 92

Expert Comment

by:objects
ID: 6890246
0

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
jdbc error in jsp application 20 74
Java exception bubble up 2 24
runtime exception 2 50
ejb example issues 3 53
By the end of 1980s, object oriented programming using languages like C++, Simula69 and ObjectPascal gained momentum. It looked like programmers finally found the perfect language. C++ successfully combined the object oriented principles of Simula w…
Basic understanding on "OO- Object Orientation" is needed for designing a logical solution to solve a problem. Basic OOAD is a prerequisite for a coder to ensure that they follow the basic design of OO. This would help developers to understand the b…
The viewer will learn how to implement Singleton Design Pattern in Java.
This tutorial will introduce the viewer to VisualVM for the Java platform application. This video explains an example program and covers the Overview, Monitor, and Heap Dump tabs.

733 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question