ExecutorServices.java
- /*******************************************************************************
- * Copyright 2013 André Rouél
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- ******************************************************************************/
- package net.sf.uadetector.internal.util;
- import java.util.ArrayList;
- import java.util.Collections;
- import java.util.HashSet;
- import java.util.List;
- import java.util.Set;
- import java.util.concurrent.ExecutorService;
- import java.util.concurrent.Executors;
- import java.util.concurrent.ScheduledExecutorService;
- import java.util.concurrent.TimeUnit;
- import javax.annotation.Nonnegative;
- import javax.annotation.Nonnull;
- import net.sf.qualitycheck.Check;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- /**
- * This utility is intended to provide predefined {@link ExecutorService}s which runs in background and can be easily
- * shut-downed within {@link #shutdownAll()} if necessary.
- *
- * @author André Rouél
- */
- public final class ExecutorServices {
- /**
- * This synchronized {@link Set} is a registry of all distributed background executors by this utility.
- * <p>
- * The containing {@link ExecutorService}s will be used to run a concrete update of <i>UAS data</i> instantly in
- * background.
- */
- private static final Set<ExecutorService> BACKGROUND_EXECUTORS = Collections.synchronizedSet(new HashSet<ExecutorService>(3));
- /**
- * Default name of a thread which will be used to run a concrete update within a background executor
- */
- private static final String DEFAULT_BACKGROUND_EXECUTOR_NAME = "update-operation";
- /**
- * Default name of a thread which will be created within a scheduler
- */
- private static final String DEFAULT_SCHEDULER_NAME = "update-scheduler";
- /**
- * Corresponding logger for this class
- */
- private static final Logger LOG = LoggerFactory.getLogger(ExecutorServices.class);
- /**
- * This synchronized {@link Set} is a registry of all distributed schedulers by this utility.
- * <p>
- * The containing {@link ScheduledExecutorService}s will be used to schedule commands which updates the <i>UAS
- * data</i> in defined intervals.
- */
- private static final Set<ScheduledExecutorService> SCHEDULERS = Collections.synchronizedSet(new HashSet<ScheduledExecutorService>(3));
- /**
- * Timeout (in seconds) to shutdown all available executors at the latest
- */
- public static final long SHUTDOWN_DURATION = 5;
- /**
- * Creates a single-threaded executor that is registered by this class in order to shut it down later (when it
- * becomes necessary).
- *
- * @return a new background executor
- */
- public static ExecutorService createBackgroundExecutor() {
- final ExecutorService executor = Executors.newSingleThreadExecutor(new DaemonThreadFactory(DEFAULT_BACKGROUND_EXECUTOR_NAME));
- BACKGROUND_EXECUTORS.add(executor);
- return executor;
- }
- /**
- * Creates a single-threaded scheduler that is registered by this class in order to shut it down later (when it
- * becomes necessary).
- *
- * @return a new scheduler
- */
- public static ScheduledExecutorService createScheduler() {
- final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1, new DaemonThreadFactory(DEFAULT_SCHEDULER_NAME));
- SCHEDULERS.add(scheduler);
- return scheduler;
- }
- /**
- * Shutdowns the given {@code ExecutorService} as soon as possible, but not later than the specified default time
- * (which is {@value #SHUTDOWN_DURATION} seconds).
- *
- * @param executorService
- * executor to stop
- */
- public static void shutdown(@Nonnull final ExecutorService executorService) {
- Check.notNull(executorService, "executorService");
- shutdown(executorService, SHUTDOWN_DURATION, TimeUnit.SECONDS);
- }
- /**
- * Shutdowns the given {@code ExecutorService} as soon as possible, but not later than the specified time.
- *
- * @param executorService
- * executor to stop
- * @param duration
- * duration as a numerical value
- * @param unit
- * duration unit
- */
- public static void shutdown(@Nonnull final ExecutorService executorService, @Nonnegative final long duration,
- @Nonnull final TimeUnit unit) {
- Check.notNull(executorService, "executorService");
- Check.notNull(duration, "duration");
- Check.notNull(unit, "unit");
- executorService.shutdown();
- try {
- if (!executorService.awaitTermination(duration, unit)) {
- LOG.info(String.format("Executor did not terminate in %s %s.", duration, unit.name().toLowerCase()));
- final List<Runnable> droppedTasks = executorService.shutdownNow();
- LOG.info("Executor was abruptly shut down. " + droppedTasks.size() + " tasks will not be executed.");
- }
- unregisterIfPossible(executorService);
- } catch (final InterruptedException e) {
- LOG.warn("Executor termination failed: " + e.getLocalizedMessage(), e);
- }
- }
- /**
- * Shuts down all registered scheduler and background workers as soon as possible, but at the latest in specified
- * {@link #SHUTDOWN_DURATION} seconds.
- */
- public static void shutdownAll() {
- for (final ExecutorService executor : new ArrayList<ExecutorService>(BACKGROUND_EXECUTORS)) {
- shutdown(executor);
- BACKGROUND_EXECUTORS.remove(executor);
- }
- for (final ScheduledExecutorService scheduler : new ArrayList<ScheduledExecutorService>(SCHEDULERS)) {
- shutdown(scheduler);
- SCHEDULERS.remove(scheduler);
- }
- }
- /**
- * Unregisters the given {@code ExecutorService} if it is an instance of {@code ScheduledExecutorService} from the
- * list of registered schedulers.
- *
- * @param executorService
- * a possible scheduler
- */
- private static void unregisterIfPossible(final ExecutorService executorService) {
- if (executorService instanceof ScheduledExecutorService) {
- SCHEDULERS.remove(executorService);
- } else {
- BACKGROUND_EXECUTORS.remove(executorService);
- }
- }
- /**
- * <strong>Attention:</strong> This class is not intended to create objects from it.
- */
- private ExecutorServices() {
- // This class is not intended to create objects from it.
- }
- }