//有时候我们需要无限循环获取数据,直到超时为止 import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Collection; import java.util.Map; public class LoopRunner { private static final Logger logger = LoggerFactory.getLogger(LoopRunner.class); private final String NO_MESSAGES_FOUND = "No messages found yet"; private static final int SLEEP_TIME = 500; private Long maxWait = 10000L; private boolean timedOut = false; public LoopRunner(long maxWait) { this.maxWait = maxWait; } public LoopRunner(Long maxWait) { this.maxWait = maxWait; } public <T> T run(LoopCondition<T> lc) { timedOut = false; T data = null; long started = System.currentTimeMillis(); ProcessTimer processTimer = new ProcessTimer(); while (System.currentTimeMillis() - started < maxWait) { String foundMessages = NO_MESSAGES_FOUND; data = lc.getData(); if (lc.test(data)) { if (data instanceof Collection<?>) { int totalCount = ((Collection<?>) data).size(); logMessageStateCounts(data, lc); logger.info("Found " + totalCount + " expected number of messages"); } return data; } try { if (data != null) foundMessages = logMessageStateCounts(data, lc); long millisecondsRemaining = maxWait - processTimer.getExecutionTimeInMilliseconds(); if (millisecondsRemaining > 0) logger.info(foundMessages + ", wait time so far: " + processTimer.getExecutionTime() + ", timing out in " + millisecondsRemaining + " ms, checking again in " + SLEEP_TIME + " ms"); Thread.sleep(SLEEP_TIME); } catch (InterruptedException e) { throw new RuntimeException(e); } } logger.warn("Timed out - could not find expected number of messages"); timedOut = true; return data; } public boolean isTimedOut() { return timedOut; } private <T> String logMessageStateCounts(T data, LoopCondition<T> lc) { Map<String, Integer> foundMessageStatusCounts = lc.getStatusCounts(data); if (foundMessageStatusCounts != null) { for (String status : foundMessageStatusCounts.keySet()) { return "Found " + foundMessageStatusCounts.get(status) + " messages with a status of " + status; } } return NO_MESSAGES_FOUND; } }
需要实现的接口:
import java.util.Map; public interface LoopCondition<T> { boolean test(T data); T getData(); Map<String, Integer> getStatusCounts(T foundMessages); }