class ExperimentManager {

    @Scheduled(fixedDelay = 15 * 1000)
    void updateExperimentStatus () {
        synchronized (allExperiments) {
            log.info("Experiments total count: {}", v("count", allExperiments.size()));
            if (!allExperiments.isEmpty()) {
                int experimentCount = Math.min(allExperiments.size(), 64);
                ForkJoinPool threadPool = null;
                try {
                    threadPool = new ForkJoinPool(experimentCount);
                    ForkJoinTask<?> threadPoolSubmit = threadPool.submit(this::evaluateExperiments);
                    threadPoolSubmit.quietlyJoin();
                } finally {
                    if (threadPool != null) threadPool.shutdown();
                }
                if (log.isDebugEnabled()) {
                    printExperimentStats();
                }
                allExperiments.removeIf(Experiment::isComplete);
                if (allExperiments.isEmpty()) {
                    setLastExperimentComplete();
                    log.info("As of {}, there are no active experiments. The next experiment can run in {}.", lastExperimentComplete, experimentBackoffPeriod);
                }
            }
        }
    }

}