org.linkedin.util-core/src/main/java/org/linkedin/util/concurrent/ConcurrentUtils.java
public static void joinUntil(Clock clock, Thread thread, long endTime)
    throws InterruptedException, TimeoutException
  {
    if(endTime <= 0)
      thread.join();
    else
    {
      while(thread.isAlive())
      {
        long now = clock.currentTimeMillis();
        if(now >= endTime)
          throw new TimeoutException("timeout reached while joining on: " + thread);
        thread.join(endTime - now);
      }
    }
  }
public static void joinUntil(Clock clock, Thread thread, long endTime)
    throws InterruptedException, TimeoutException
  {
    if(endTime <= 0)
      thread.join();
    else
    {
      while(thread.isAlive())
      {
        long now = clock.currentTimeMillis();
        if(now >= endTime)
          throw new TimeoutException("timeout reached while joining on: " + thread);
        thread.join(endTime - now);
      }
    }
  }
Joins on the thread but if end time is expired then throws an exception.

@param thread the thread to join on
@param endTime the time after which an exception is thrown (compared
to {@link java.lang.System#currentTimeMillis()}. If &lt;= 0 then wait
indefinitely (so <code>TimeOutException</code> will not be thrown!)
@throws InterruptedException if the thread is interrupted while waiting
@throws TimeoutException if the time has been reached