public V getValue() {
        // If uninitialised or we have passed the next check time then get the state
        // to see if it has changed. If it has then update the value.
        if (checkUpdateRequired().isUpdateRequired) {
            synchronized (this) {
                // Recheck under lock
                final CheckResult<S> checkResult = checkUpdateRequired();
                if (checkResult.isUpdateRequired) {
                    final V newValue = valueSupplier.apply(checkResult.newState);
                    LOGGER.debug(() -> LogUtil.message(
                            "Updating value - nextCheck: {}, state: {}, newState: {}, value: {}, newValue: {}",
                            nextCheckEpochMs.get(), state, checkResult.newState, value, newValue));
                    state = checkResult.newState;
                    value = newValue;
                    nextCheckEpochMs.set(System.currentTimeMillis() + checkIntervalMs);
                }
            }
        }
        LOGGER.debug("Returning {}", value);
        return value;
    }
Gets the updatable value. If it has not been updated for longer than maxCheckInterval
then the state will be fetched and, if the state has changed, the value will be
updated synchronously.
stroom-util/src/main/java/stroom/util/concurrent/CachedValue.java