Skip to content

Instantly share code, notes, and snippets.

@henrrich
Created August 11, 2016 06:44
Show Gist options
  • Save henrrich/e89a14446196cfcb11201f1df5adc5c9 to your computer and use it in GitHub Desktop.
Save henrrich/e89a14446196cfcb11201f1df5adc5c9 to your computer and use it in GitHub Desktop.
Running task in seperated thread using executor framework and handles timeout
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.*;
/**
* Created by hehuan on 10/08/2016.
*
* This class uses a single thread to execute the task assigned to it and wait for the result.
* User can specify the total timeout for finishing task as well as time out for each individual task iteration.
* If a task times out, but the total timeout has not been reached, this class will retry the task again in a new thread.
*/
public class WaitUtil {
private static Logger logger = LoggerFactory.getLogger(WaitUtil.class);
private ExecutorService executorService;
private long totalTimeout;
private long taskTimeout;
private Callable task;
/**
* Constructor
*
* @param totalTimeout long total timeout in seconds
* @param taskTimeout long timeout for each task computation
* @param task Callable task reference
*/
public WaitUtil(long totalTimeout, long taskTimeout, Callable task) {
this.totalTimeout = totalTimeout;
this.taskTimeout = taskTimeout;
this.task = task;
this.executorService = Executors.newSingleThreadExecutor();
}
/**
* This method will execute the task in a thread and wait for its result.
* If individual task computation times out, the method will retry the task in a new thread until total timeout is reached.
*
* @return Object task computation result
* @throws TimeoutException throw TimeoutException if total timeout is reached
*/
public Object waitForTaskDone() throws TimeoutException {
long expectedTimeout = System.currentTimeMillis() + totalTimeout * 1000L;
while (true) {
if (System.currentTimeMillis() < expectedTimeout) {
logger.info("Start to execute task " + task.getClass() + " in a seperate thread!");
Future future = executorService.submit(task);
try {
Object result = future.get(taskTimeout, TimeUnit.SECONDS);
close();
return result;
} catch (Exception e) {
logger.warn("Timeout or failure to execute task " + task.getClass() + ": " + e.getMessage());
future.cancel(true);
}
} else {
close();
throw new TimeoutException("Failed to complete task " + task.getClass() + " within " + totalTimeout + " seconds!");
}
}
}
private void close() {
if (!executorService.isShutdown()) {
executorService.shutdownNow();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment