6

i have to write a "WatchDog" in Java, who secure that Threads don't perform too long. With the initialization of the Objects it's no Problem, i made a Class, who calls the WatchDog and the constructor with reflections in the run() method.

A Thread is easy to stop, but how i can secure normal methods of objects? For example i call the method of an Object and this method perform a endless loop, how you would do that?

thanks

Nicolas
  • 269
  • 4
  • 14
  • "A thread is easy to stop", no, it's not. I don't understand "how i can secure normal methods of objects?", neither the example that follows with the endless loop. – toto2 Aug 09 '11 at 12:54
  • http://download.oracle.com/javase/7/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html Read all of that, and then check that you still want to call stop(). Maybe some thinking outside of the proverbial box is necessary to work around your problem. – RichColours Aug 11 '11 at 08:40
  • i wan't to make a game, where you can develope the strategy, and if they do an while(1); i have to kill them, do you now understand what i mean? – Nicolas Aug 11 '11 at 11:09

3 Answers3

4

First, I should point out that stopping a thread is NOT easy. In fact, in the general case, threads cannot be stopped safely:

  • You can call Thread.interrupt() on a thread the you want to stop, but there is no guarantee that the thread will notice the interrupt, let alone actually stop.

  • You can call the deprecated Thread.stop() method, but this method is unsafe. If you call it at an unfortunate moment, you can leave data structures in a half-updated state, leave other threads waiting (for ever) on signals that won't arrive and so on.


Here's how I'd implement a watchdog for method execution.

First I'd modify the method to add two calls to the watchdog service; e.g.

public void someMethod(...) {
    Watchdog.startMethod(maxTime);
    // do stuff
    Watchdog.endMethod();
}

Next, I'd implement the Watchdog with a priority queue ordered on expiry time:

  1. The startMethod(maxTime) would add an entry to the queue with expiry time of now + maxTime. The entry would include a reference to the current thread (when the method was called.
  2. The endMethod() would look for a (the) queue entry for the current thread, and remove it if found.
  3. The watchdog thread would periodically look at the first queue entry. If that entry had an expiry less than 'now', the watchdog would remove the entry, stop its thread and check the next entry. Repeat until the next entry hasn't expired.

Some thought would need to be given to the data structures, and to dealing with cases where endMethod calls get skipped. (Indeed, since a method call can terminate due to an exception, the endMethod() call really needs to be done in a finally block.)

Note that the startMethod and endMethod calls could (and maybe should) be inserted by an annotation processor or something like that.


Given the complexity, and the fact that you can't guarantee to stop the thread (safely), I'd think of some solution that doesn't involve a method watchdog.

Community
  • 1
  • 1
Stephen C
  • 632,615
  • 86
  • 730
  • 1,096
  • This is correct way of solving the problem. No idea why it's not picked as answer. If someone wants out of the box solution try @ Timeable as @yegor256 presented. But it doesnt solve the problem of "Cleaning after interuption". Personally i would still write my own aspect. – Daniel Hajduk Nov 06 '15 at 13:56
3

Normal methods of objects are running on some thread. It might be the AWT event dispatcher or whatever it's called. Or it might be the main thread, say, of a console application.

They are no different to the threads that are called with new Thread().

I guess your watchdog needs to be looking at all the threads in the VM and looking for ones which have a utilisation >= some threshold.

What code do you have so far?

Rich

RichColours
  • 650
  • 1
  • 4
  • 14
  • okey, maybe i described it wrong, i give my watchdog all threads i want to observe. I only want to initialize the Object and run every method in a thread, and give that thread to my watchdog. – Nicolas Aug 09 '11 at 12:06
  • Hi Nicolas Can you elabourate on this? Specifically the "I only want to initialize the Object and run every method in a thread, and give that thread to my watchdog." part. I can likely help, but I do not understand what you're doing. – RichColours Aug 09 '11 at 12:42
  • Here is my code for a secure instance and a secure method calling: http://pastebin.com/v8kdvdUW Hope you can understand what I want to do. – Nicolas Aug 09 '11 at 17:48
  • Hi Nicolas Just had a look. Is there a class Watchdog that you've not pastebined? Also, you've got in several places try-catch where you're effectively ignoring InterruptedException. You absolutely cannot ignore that Exception. In my experience, all the thread operations can and DO get interrupted; the scheduler wakes them up for god know's what reason, and then they throw that exception. You have to have a little loop around those try-catch blocks looking for the exit condition. – RichColours Aug 10 '11 at 09:19
1

Try to use @Timeable annotation from jcabi-aspects:

public class Resource {
  @Timeable(limit = 5, unit = TimeUnit.SECONDS)
  public String load(URL url) {
    return url.openConnection().getContent();
  }
}

Your method will be interrupted on timeout.

yegor256
  • 93,933
  • 106
  • 409
  • 558