user964843
user964843

Reputation:

Immediately kill a running future thread

I'm using

(def f 
   (future 
      (while (not (Thread/interrupted)) 
         (function-to-run))))

(Thread/sleep 100)
(future-cancel f)

to cancel my code after a specified amount of time (100ms).
The problem is, I need to cancel the already running function 'function-to-run' as well, it is important that it really stops executing that function after 100ms.
Can I somehow propagate the interrupted signal to the function?
The function is not third-party, I wrote it myself.

Upvotes: 7

Views: 2077

Answers (1)

Josh
Josh

Reputation: 4806

The basic thing to note here is: you cannot safely kill a thread without its own cooperation. Since you are the owner of the function you wish to be able to kill prematurely, it makes sense to allow the function to cooperate and die gracefully and safely.

(defn function-to-run
  []
  (while work-not-done
    (if-not (Thread/interrupted)
      ; ... do your work
      (throw (InterruptedException. "Function interrupted...")))))

(def t (Thread. (fn []
                  (try
                    (while true
                      (function-to-run))
                    (catch InterruptedException e
                      (println (.getMessage e)))))))

To begin the thread

(.start t)

To interrupt it:

(.interrupt t)

Your approach was not sufficient for your use case because the while condition was checked only after control flow returned from function-to-run, but you wanted to stop function-to-run during its execution. The approach here is only different in that the condition is checked more frequently, namely, every time through the loop in function-to-run. Note that instead of throwing an exception from function-to-run, you could also return some value indicating an error, and as long as your loop in the main thread checks for this value, you don't have to involve exceptions at all.

If your function-to-run doesn't feature a loop where you can perform the interrupted check, then it likely is performing some blocking I/O. You may not be able to interrupt this, though many APIs will allow you to specify a timeout on the operation. In the worst case, you can still perform intermittent checks for interrupted in the function around your calls. But the bottom line still applies: you cannot safely forcibly stop execution of code running in the function; it should yield control cooperatively.

Note: My original answer here involved presenting an example in which java's Thread.stop() was used (though strongly discouraged). Based on feedback in the comments, I revised the answer to the one above.

Upvotes: 5

Related Questions