/* * Copyright 2004-2014 H2 Group. Multiple-Licensed under the MPL 2.0, * and the EPL 1.0 (http://h2database.com/html/license.html). * Initial Developer: H2 Group */ package org.h2.util; import java.util.concurrent.atomic.AtomicInteger; /** * A method call that is executed in a separate thread. If the method throws an * exception, it is wrapped in a RuntimeException. */ public abstract class Task implements Runnable { private static AtomicInteger counter = new AtomicInteger(); /** * A flag indicating the get() method has been called. */ public volatile boolean stop; /** * The result, if any. */ protected Object result; private volatile boolean finished; private Thread thread; private Exception ex; /** * The method to be implemented. * * @throws Exception any exception is wrapped in a RuntimeException */ public abstract void call() throws Exception; @Override public void run() { try { call(); } catch (Exception e) { this.ex = e; } finished = true; } /** * Start the thread. * * @return this */ public Task execute() { return execute(getClass().getName() + ":" + counter.getAndIncrement()); } /** * Start the thread. * * @param threadName the name of the thread * @return this */ public Task execute(String threadName) { thread = new Thread(this, threadName); thread.setDaemon(true); thread.start(); return this; } /** * Calling this method will set the stop flag and wait until the thread is * stopped. * * @return the result, or null * @throws RuntimeException if an exception in the method call occurs */ public Object get() { Exception e = getException(); if (e != null) { throw new RuntimeException(e); } return result; } /** * Whether the call method has returned (with or without exception). * * @return true if yes */ public boolean isFinished() { return finished; } /** * Interrupt the thread. */ public void interruptThread() { if (thread == null) { throw new IllegalStateException("Thread not started"); } thread.interrupt(); } /** * Get the exception that was thrown in the call (if any). * * @return the exception or null */ public Exception getException() { join(); if (ex != null) { return ex; } return null; } /** * Stop the thread and wait until it is no longer running. Exceptions are * ignored. */ public void join() { stop = true; if (thread == null) { throw new IllegalStateException("Thread not started"); } try { thread.join(); } catch (InterruptedException e) { // ignore } } }