saadi
saadi

Reputation: 714

How to set thread timeout

I have this scala code, which works just fine (run() is overridden in class)

val processRunnable = new myProcessClassWithOverriddenRunFunction()
val processThread = new Thread(processRunnable)
processThread.start

What I want to do is set a timeout for processThread thread. How can I do that?

I did some research and couldn't find any parameter we can pass to new Thread() or any function in processThread to achieve that.

Found some solutions on stackoveflow which implemented a ExecutorService but unfortunately, that is not implementable in this particular problem as making another new ExecutorService for just a single processThread, everytime this function is called seems inefficient. There are some other reasons as well but my question is how can I implement that functionality on this code?

Upvotes: 1

Views: 314

Answers (2)

daniu
daniu

Reputation: 15018

In Java, you can use

CompletableFuture<Void> future = CompletableFuture.runAsync(processRunnable);
future.get(1000, TimeUnit.MILLISECONDS);

To future.get function will throw a TimeOutException when timeout (1 second in the example above) is reached and the timeout case can be handled in catch block.
Complete code will be something like this:

try {
     CompletableFuture<Void> future = CompletableFuture.runAsync(processRunnable);
    future.get(1000, TimeUnit.MILLISECONDS);
}
catch{
case texc : TimeoutException => println("Timeout is reached.")
case exc  : Exception => println(exc.getmessage)
}

Upvotes: 1

rustyx
rustyx

Reputation: 85531

There is no way to achieve that without the thread cooperating. This is similar in nature to how to make a thread interruptible, and has to do with the fact that it is in general unsafe to stop running threads asynchronously (and a timeout is asynchronous).

Your thread needs to include the timeout capability as part of it's implementation, so that it can act on a timeout condition when it is safe for it to do so.

For example:

public class MyProcessClass {
    private final long timeoutMillis = 30000;
    public void run() {
        long timeout = System.currentTimeMillis() + timeoutMillis;
        while (System.currentTimeMillis() < timeout) {
            // Process next chunk of work
        }
    }
}

PS. Don't be misled by the other answer based on the ExecutorService - it requires the thread to be interruptible, i.e. the same solution as shown above.

        while (!Thread.interrupted()) {
            // Process next chunk of work
        }

Upvotes: 3

Related Questions