1

TL;DR Is it OK to a Java thread when I know it isn't synchronized to anything else?

First I'll describe my predicament. I have a service that handles requests from an app (both on the same machine). This service is single threaded. In some cases, answering requests can take a while. I'd like to time out the request in those cases. Sadly, it's quite complicated to poll interrupts inside said service, as it has quite expansive algorithmic logic, and would cause lots of ugly code rewriting.

Think of the service as a facade that calls a library of scary algorithmic stuff. Currently the service simply calls the library upon request, I want it to start a thread, and time it out if computation takes too long. I intend on using just a single extra thread.

I read How do you kill a thread in Java? and https://docs.oracle.com/javase/1.5.0/docs/guide/misc/threadPrimitiveDeprecation.html

According to these, stopping a thread is deprecated because of loss of synchronization. However, my service is basically single threaded, and thus has no need for synchronization.

In this case, is it OK for me to stop the thread? Am I missing some internal java stuff?

Thanks!

lavuy
  • 191
  • 1
  • 12
  • 3
    Could you share the code? – egorlitvinenko Jan 08 '18 at 07:11
  • 3
    It is single threaded, but you want to stop the thread? So does that mean you want to exit the process? – matt Jan 08 '18 at 07:11
  • @egorlitvinenko Hmmm... I don't think I can. However, I don't think you really need it here. Think of the service as a facade for a library with several methods, which are all algorithmic and scary. – lavuy Jan 08 '18 at 07:15
  • @matt Currently, the service simply runs some code. I want the service to run the code on a different thread, and kill the thread if the running takes too long – lavuy Jan 08 '18 at 07:17
  • You could use futures (in particular CompletableFuture) for that and that's all, do you? – egorlitvinenko Jan 08 '18 at 07:20
  • @egorlitvinenko I don't think this would work :\ I need to be able kill the future, without modifying the code it calls. – lavuy Jan 08 '18 at 07:26
  • You could do it with cancel method, see my example below. – egorlitvinenko Jan 08 '18 at 07:27
  • Guys, I really appreciate the help, but I'm aware of multi-threading best practices in Java. I just want to know, if in my case it's OK to digress from them. – lavuy Jan 08 '18 at 07:31
  • 1
    One thing you can do, instead of starting another thread is to start another process. Then you have full control to start or stop that process. That is essentially how you are describing your spawned thread. – matt Jan 08 '18 at 07:40

1 Answers1

3

So you have a service that processes requests, and sometimes that processing can take a while. You want to impose some maximum amount of time your service could spend processing that request before giving up.

You don't want to litter your code with checks to a flag that would be set by some interrupt, because the code is large and complicated.

Your options:

  1. Don't give up.

Process each request on a separate thread. Allow each request to run to completion, taking as much time as necessary. Consider improving the service request code, perhaps using parallelism, to reduce the amount of time it takes to run.

  1. Litter your code with 'time to stop' checks.

This is the second best answer - you have controlled access over where your program decides to stop processing the response. Your program can controllably shut down the request processing, properly cleaning up whatever it needs to (perhaps open resources such as files, sockets, etc; resetting program state internally).

  1. Kill the thread.

Calling Thread.stop() is deprecated, and for good reason - it can corrupt synchronization state. If your request handling logic uses any form of synchronization, then you'll cause corruption. Keep in mind that synchronization is used everywhere, even if you don't see it. Reading from a file uses a form of synchronization. Writing to the standard out uses synchronization.

This is possible, but it's a terrible idea.

...

There are other strategies related to #2 - for instance, you could restructure your program so that each section of processing is created as a job on a queue, that one thread is responsible for dequeuing and executing - basically, the message pump pattern. In this design, you'd have a nice choke point at which to put your 'timed out' logic. This is the design used by most windowing frameworks - the UI message pump.

antiduh
  • 11,853
  • 4
  • 43
  • 66
  • Thanks! That's exactly what I was looking for. – lavuy Jan 08 '18 at 07:34
  • Your point 3 is a bit overdramatic. Thread.stop is no worse than an OutOfMemoryError or any other unexpected RuntimeException or Error. They're all bad, they can corrupt the invariants of any data structure, including ones shared by multiple threads. It doesn't leave any monitors locked, and it doesn't corrupt file reading either nor standard output (that's OS-level stuff, unaffected by Thread.stop) . Thread.stop throws an unexpected exception into the thread, that you could handle in your code if you wanted to. Still, it should be avoided in clean, production, code. – Erwin Bolwidt Jan 08 '18 at 07:41
  • Could you explain or provide links, how we can handle timeouts in queue processing, without affecting the original code in Java? – egorlitvinenko Jan 08 '18 at 07:48
  • 1
    @egorlitvinenko - that was the central thesis of #2: you can't. You have to modify or restructure the code in some way, but if you're willing to do so, there are multiple strategies you can use. You generally can't make your code respond to a stimuli if you're not looking for it. – antiduh Jan 08 '18 at 16:29