package io.dropwizard.metrics; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; /** * Factory and utility methods for {@link InstrumentedExecutorService}, * {@link InstrumentedScheduledExecutorService}, and {@link InstrumentedThreadFactory} * classes defined in this package. This class supports the following kinds of methods: * <p> * <ul> * <li> Methods that create and return an {@link InstrumentedExecutorService} * set up with commonly useful configuration settings. * <li> Methods that create and return a {@link InstrumentedScheduledExecutorService} * set up with commonly useful configuration settings. * <li> Methods that create and return a "wrapped" ExecutorService, that * disables reconfiguration by making implementation-specific methods * inaccessible. * <li> Methods that create and return a {@link InstrumentedThreadFactory} * that sets newly created threads to a known state. * </ul> * </p> * * @see java.util.concurrent.Executors */ public final class InstrumentedExecutors { /** * Creates an instrumented thread pool that reuses a fixed number of threads * operating off a shared unbounded queue. At any point, at most * {@code nThreads} threads will be active processing tasks. * If additional tasks are submitted when all threads are active, * they will wait in the queue until a thread is available. * If any thread terminates due to a failure during execution * prior to shutdown, a new one will take its place if needed to * execute subsequent tasks. The threads in the pool will exist * until it is explicitly {@link ExecutorService#shutdown shutdown}. * * @param nThreads the number of threads in the pool * @param registry the {@link MetricRegistry} that will contain the metrics. * @param name the (metrics) name for this executor service, see {@link MetricRegistry#name(String, String...)}. * @return the newly created thread pool * @throws IllegalArgumentException if {@code nThreads <= 0} * @see Executors#newFixedThreadPool(int) */ public static InstrumentedExecutorService newFixedThreadPool(int nThreads, MetricRegistry registry, String name) { return new InstrumentedExecutorService(Executors.newFixedThreadPool(nThreads), registry, name); } /** * Creates an instrumented thread pool that reuses a fixed number of threads * operating off a shared unbounded queue. At any point, at most * {@code nThreads} threads will be active processing tasks. * If additional tasks are submitted when all threads are active, * they will wait in the queue until a thread is available. * If any thread terminates due to a failure during execution * prior to shutdown, a new one will take its place if needed to * execute subsequent tasks. The threads in the pool will exist * until it is explicitly {@link java.util.concurrent.ExecutorService#shutdown shutdown}. * * @param nThreads the number of threads in the pool * @param registry the {@link MetricRegistry} that will contain the metrics. * @return the newly created thread pool * @throws IllegalArgumentException if {@code nThreads <= 0} * @see Executors#newFixedThreadPool(int) */ public static InstrumentedExecutorService newFixedThreadPool(int nThreads, MetricRegistry registry) { return new InstrumentedExecutorService(Executors.newFixedThreadPool(nThreads), registry); } /** * Creates an instrumented thread pool that reuses a fixed number of threads * operating off a shared unbounded queue, using the provided * ThreadFactory to create new threads when needed. At any point, * at most {@code nThreads} threads will be active processing * tasks. If additional tasks are submitted when all threads are * active, they will wait in the queue until a thread is * available. If any thread terminates due to a failure during * execution prior to shutdown, a new one will take its place if * needed to execute subsequent tasks. The threads in the pool will * exist until it is explicitly {@link ExecutorService#shutdown shutdown}. * * @param nThreads the number of threads in the pool * @param threadFactory the factory to use when creating new threads * @param registry the {@link MetricRegistry} that will contain the metrics. * @param name the (metrics) name for this executor service, see {@link MetricRegistry#name(String, String...)}. * @return the newly created thread pool * @throws NullPointerException if threadFactory is null * @throws IllegalArgumentException if {@code nThreads <= 0} * @see Executors#newFixedThreadPool(int, ThreadFactory) */ public static InstrumentedExecutorService newFixedThreadPool( int nThreads, ThreadFactory threadFactory, MetricRegistry registry, String name) { return new InstrumentedExecutorService(Executors.newFixedThreadPool(nThreads, threadFactory), registry, name); } /** * Creates a thread pool that reuses a fixed number of threads * operating off a shared unbounded queue, using the provided * ThreadFactory to create new threads when needed. At any point, * at most {@code nThreads} threads will be active processing * tasks. If additional tasks are submitted when all threads are * active, they will wait in the queue until a thread is * available. If any thread terminates due to a failure during * execution prior to shutdown, a new one will take its place if * needed to execute subsequent tasks. The threads in the pool will * exist until it is explicitly {@link ExecutorService#shutdown * shutdown}. * * @param nThreads the number of threads in the pool * @param threadFactory the factory to use when creating new threads * @param registry the {@link MetricRegistry} that will contain the metrics. * @return the newly created thread pool * @throws NullPointerException if threadFactory is null * @throws IllegalArgumentException if {@code nThreads <= 0} * @see Executors#newFixedThreadPool(int, ThreadFactory) */ public static InstrumentedExecutorService newFixedThreadPool( int nThreads, ThreadFactory threadFactory, MetricRegistry registry) { return new InstrumentedExecutorService(Executors.newFixedThreadPool(nThreads, threadFactory), registry); } /** * Creates an InstrumentedExecutor that uses a single worker thread operating * off an unbounded queue. (Note however that if this single * thread terminates due to a failure during execution prior to * shutdown, a new one will take its place if needed to execute * subsequent tasks.) Tasks are guaranteed to execute * sequentially, and no more than one task will be active at any * given time. Unlike the otherwise equivalent * {@code newFixedThreadPool(1)} the returned executor is * guaranteed not to be reconfigurable to use additional threads. * * @param registry the {@link MetricRegistry} that will contain the metrics. * @param name the (metrics) name for this executor service, see {@link MetricRegistry#name(String, String...)}. * @return the newly created single-threaded Executor * @see Executors#newSingleThreadExecutor() */ public static InstrumentedExecutorService newSingleThreadExecutor(MetricRegistry registry, String name) { return new InstrumentedExecutorService(Executors.newSingleThreadExecutor(), registry, name); } /** * Creates an Executor that uses a single worker thread operating * off an unbounded queue. (Note however that if this single * thread terminates due to a failure during execution prior to * shutdown, a new one will take its place if needed to execute * subsequent tasks.) Tasks are guaranteed to execute * sequentially, and no more than one task will be active at any * given time. Unlike the otherwise equivalent * {@code newFixedThreadPool(1)} the returned executor is * guaranteed not to be reconfigurable to use additional threads. * * @param registry the {@link MetricRegistry} that will contain the metrics. * @return the newly created single-threaded Executor * @see Executors#newSingleThreadExecutor() */ public static InstrumentedExecutorService newSingleThreadExecutor(MetricRegistry registry) { return new InstrumentedExecutorService(Executors.newSingleThreadExecutor(), registry); } /** * Creates an InstrumentedExecutor that uses a single worker thread operating * off an unbounded queue, and uses the provided ThreadFactory to * create a new thread when needed. Unlike the otherwise * equivalent {@code newFixedThreadPool(1, threadFactory)} the * returned executor is guaranteed not to be reconfigurable to use * additional threads. * * @param threadFactory the factory to use when creating new threads * @param registry the {@link MetricRegistry} that will contain the metrics. * @param name the (metrics) name for this executor service, see {@link MetricRegistry#name(String, String...)}. * @return the newly created single-threaded Executor * @throws NullPointerException if threadFactory is null * @see Executors#newSingleThreadExecutor(ThreadFactory) */ public static InstrumentedExecutorService newSingleThreadExecutor( ThreadFactory threadFactory, MetricRegistry registry, String name) { return new InstrumentedExecutorService(Executors.newSingleThreadExecutor(threadFactory), registry, name); } /** * Creates an InstrumentedExecutor that uses a single worker thread operating * off an unbounded queue, and uses the provided ThreadFactory to * create a new thread when needed. Unlike the otherwise * equivalent {@code newFixedThreadPool(1, threadFactory)} the * returned executor is guaranteed not to be reconfigurable to use * additional threads. * * @param threadFactory the factory to use when creating new threads * @param registry the {@link MetricRegistry} that will contain the metrics. * @return the newly created single-threaded Executor * @throws NullPointerException if threadFactory is null * @see Executors#newSingleThreadExecutor(ThreadFactory) */ public static InstrumentedExecutorService newSingleThreadExecutor( ThreadFactory threadFactory, MetricRegistry registry) { return new InstrumentedExecutorService(Executors.newSingleThreadExecutor(threadFactory), registry); } /** * Creates an instrumented thread pool that creates new threads as needed, but * will reuse previously constructed threads when they are * available. These pools will typically improve the performance * of programs that execute many short-lived asynchronous tasks. * Calls to {@code execute} will reuse previously constructed * threads if available. If no existing thread is available, a new * thread will be created and added to the pool. Threads that have * not been used for sixty seconds are terminated and removed from * the cache. Thus, a pool that remains idle for long enough will * not consume any resources. Note that pools with similar * properties but different details (for example, timeout parameters) * may be created using {@link ThreadPoolExecutor} constructors. * * @param registry the {@link MetricRegistry} that will contain the metrics. * @param name the (metrics) name for this executor service, see {@link MetricRegistry#name(String, String...)}. * @return the newly created thread pool * @see Executors#newCachedThreadPool() */ public static InstrumentedExecutorService newCachedThreadPool(MetricRegistry registry, String name) { return new InstrumentedExecutorService(Executors.newCachedThreadPool(), registry, name); } /** * Creates an instrumented thread pool that creates new threads as needed, but * will reuse previously constructed threads when they are * available. These pools will typically improve the performance * of programs that execute many short-lived asynchronous tasks. * Calls to {@code execute} will reuse previously constructed * threads if available. If no existing thread is available, a new * thread will be created and added to the pool. Threads that have * not been used for sixty seconds are terminated and removed from * the cache. Thus, a pool that remains idle for long enough will * not consume any resources. Note that pools with similar * properties but different details (for example, timeout parameters) * may be created using {@link ThreadPoolExecutor} constructors. * * @param registry the {@link MetricRegistry} that will contain the metrics. * @return the newly created thread pool * @see Executors#newCachedThreadPool() */ public static InstrumentedExecutorService newCachedThreadPool(MetricRegistry registry) { return new InstrumentedExecutorService(Executors.newCachedThreadPool(), registry); } /** * Creates an instrumented thread pool that creates new threads as needed, but * will reuse previously constructed threads when they are * available, and uses the provided * ThreadFactory to create new threads when needed. * * @param threadFactory the factory to use when creating new threads * @param registry the {@link MetricRegistry} that will contain the metrics. * @param name the (metrics) name for this executor service, see {@link MetricRegistry#name(String, String...)}. * @return the newly created thread pool * @throws NullPointerException if threadFactory is null * @see Executors#newCachedThreadPool(ThreadFactory) */ public static InstrumentedExecutorService newCachedThreadPool( ThreadFactory threadFactory, MetricRegistry registry, String name) { return new InstrumentedExecutorService( Executors.newCachedThreadPool(threadFactory), registry, name); } /** * Creates an instrumented thread pool that creates new threads as needed, but * will reuse previously constructed threads when they are * available, and uses the provided * ThreadFactory to create new threads when needed. * * @param threadFactory the factory to use when creating new threads * @param registry the {@link MetricRegistry} that will contain the metrics. * @return the newly created thread pool * @throws NullPointerException if threadFactory is null * @see Executors#newCachedThreadPool(ThreadFactory) */ public static InstrumentedExecutorService newCachedThreadPool( ThreadFactory threadFactory, MetricRegistry registry) { return new InstrumentedExecutorService(Executors.newCachedThreadPool(threadFactory), registry); } /** * Creates a single-threaded instrumented executor that can schedule commands * to run after a given delay, or to execute periodically. * (Note however that if this single * thread terminates due to a failure during execution prior to * shutdown, a new one will take its place if needed to execute * subsequent tasks.) Tasks are guaranteed to execute * sequentially, and no more than one task will be active at any * given time. Unlike the otherwise equivalent * {@code newScheduledThreadPool(1)} the returned executor is * guaranteed not to be reconfigurable to use additional threads. * * @param registry the {@link MetricRegistry} that will contain the metrics. * @param name the (metrics) name for this executor service, see {@link MetricRegistry#name(String, String...)}. * @return the newly created scheduled executor * @see Executors#newSingleThreadScheduledExecutor() */ public static InstrumentedScheduledExecutorService newSingleThreadScheduledExecutor( MetricRegistry registry, String name) { return new InstrumentedScheduledExecutorService (Executors.newSingleThreadScheduledExecutor(), registry, name); } /** * Creates a single-threaded instrumented executor that can schedule commands * to run after a given delay, or to execute periodically. * (Note however that if this single * thread terminates due to a failure during execution prior to * shutdown, a new one will take its place if needed to execute * subsequent tasks.) Tasks are guaranteed to execute * sequentially, and no more than one task will be active at any * given time. Unlike the otherwise equivalent * {@code newScheduledThreadPool(1)} the returned executor is * guaranteed not to be reconfigurable to use additional threads. * * @param registry the {@link MetricRegistry} that will contain the metrics. * @return the newly created scheduled executor * @see Executors#newSingleThreadScheduledExecutor() */ public static InstrumentedScheduledExecutorService newSingleThreadScheduledExecutor(MetricRegistry registry) { return new InstrumentedScheduledExecutorService(Executors.newSingleThreadScheduledExecutor(), registry); } /** * Creates a single-threaded instrumented executor that can schedule commands * to run after a given delay, or to execute periodically. (Note * however that if this single thread terminates due to a failure * during execution prior to shutdown, a new one will take its * place if needed to execute subsequent tasks.) Tasks are * guaranteed to execute sequentially, and no more than one task * will be active at any given time. Unlike the otherwise * equivalent {@code newScheduledThreadPool(1, threadFactory)} * the returned executor is guaranteed not to be reconfigurable to * use additional threads. * * @param threadFactory the factory to use when creating new threads * @param registry the {@link MetricRegistry} that will contain the metrics. * @param name the (metrics) name for this executor service, see {@link MetricRegistry#name(String, String...)}. * @return a newly created scheduled executor * @throws NullPointerException if threadFactory is null * @see Executors#newSingleThreadExecutor(ThreadFactory) */ public static InstrumentedScheduledExecutorService newSingleThreadScheduledExecutor( ThreadFactory threadFactory, MetricRegistry registry, String name) { return new InstrumentedScheduledExecutorService( Executors.newSingleThreadScheduledExecutor(threadFactory), registry, name); } /** * Creates a single-threaded instrumented executor that can schedule commands * to run after a given delay, or to execute periodically. (Note * however that if this single thread terminates due to a failure * during execution prior to shutdown, a new one will take its * place if needed to execute subsequent tasks.) Tasks are * guaranteed to execute sequentially, and no more than one task * will be active at any given time. Unlike the otherwise * equivalent {@code newScheduledThreadPool(1, threadFactory)} * the returned executor is guaranteed not to be reconfigurable to * use additional threads. * * @param threadFactory the factory to use when creating new threads * @param registry the {@link MetricRegistry} that will contain the metrics. * @return a newly created scheduled executor * @throws NullPointerException if threadFactory is null * @see Executors#newSingleThreadExecutor(ThreadFactory) */ public static InstrumentedScheduledExecutorService newSingleThreadScheduledExecutor( ThreadFactory threadFactory, MetricRegistry registry) { return new InstrumentedScheduledExecutorService( Executors.newSingleThreadScheduledExecutor(threadFactory), registry); } /** * Creates an instrumented thread pool that can schedule commands to run after a * given delay, or to execute periodically. * * @param corePoolSize the number of threads to keep in the pool, * even if they are idle * @param registry the {@link MetricRegistry} that will contain the metrics. * @param name the (metrics) name for this executor service, see {@link MetricRegistry#name(String, String...)}. * @return a newly created scheduled thread pool * @throws IllegalArgumentException if {@code corePoolSize < 0} * @see Executors#newScheduledThreadPool(int) */ public static InstrumentedScheduledExecutorService newScheduledThreadPool( int corePoolSize, MetricRegistry registry, String name) { return new InstrumentedScheduledExecutorService( Executors.newScheduledThreadPool(corePoolSize), registry, name); } /** * Creates an instrumented thread pool that can schedule commands to run after a * given delay, or to execute periodically. * * @param corePoolSize the number of threads to keep in the pool, * even if they are idle * @param registry the {@link MetricRegistry} that will contain the metrics. * @return a newly created scheduled thread pool * @throws IllegalArgumentException if {@code corePoolSize < 0} * @see Executors#newScheduledThreadPool(int) */ public static InstrumentedScheduledExecutorService newScheduledThreadPool( int corePoolSize, MetricRegistry registry) { return new InstrumentedScheduledExecutorService( Executors.newScheduledThreadPool(corePoolSize), registry); } /** * Creates an instrumented thread pool that can schedule commands to run after a * given delay, or to execute periodically. * * @param corePoolSize the number of threads to keep in the pool, * even if they are idle * @param threadFactory the factory to use when the executor * creates a new thread * @param registry the {@link MetricRegistry} that will contain the metrics. * @param name the (metrics) name for this executor service, see {@link MetricRegistry#name(String, String...)}. * @return a newly created scheduled thread pool * @throws IllegalArgumentException if {@code corePoolSize < 0} * @throws NullPointerException if threadFactory is null * @see Executors#newScheduledThreadPool(int, ThreadFactory) */ public static InstrumentedScheduledExecutorService newScheduledThreadPool( int corePoolSize, ThreadFactory threadFactory, MetricRegistry registry, String name) { return new InstrumentedScheduledExecutorService( Executors.newScheduledThreadPool(corePoolSize, threadFactory), registry, name); } /** * Creates an instrumented thread pool that can schedule commands to run after a * given delay, or to execute periodically. * * @param corePoolSize the number of threads to keep in the pool, even if they are idle * @param threadFactory the factory to use when the executor creates a new thread * @param registry the {@link MetricRegistry} that will contain the metrics. * @return a newly created scheduled thread pool * @throws IllegalArgumentException if {@code corePoolSize < 0} * @throws NullPointerException if threadFactory is null * @see Executors#newScheduledThreadPool(int, ThreadFactory) */ public static InstrumentedScheduledExecutorService newScheduledThreadPool( int corePoolSize, ThreadFactory threadFactory, MetricRegistry registry) { return new InstrumentedScheduledExecutorService( Executors.newScheduledThreadPool(corePoolSize, threadFactory), registry); } /** * Returns an instrumented default thread factory used to create new threads. * This factory creates all new threads used by an Executor in the * same {@link ThreadGroup}. If there is a {@link * java.lang.SecurityManager}, it uses the group of {@link * System#getSecurityManager}, else the group of the thread * invoking this {@code defaultThreadFactory} method. Each new * thread is created as a non-daemon thread with priority set to * the smaller of {@code Thread.NORM_PRIORITY} and the maximum * priority permitted in the thread group. New threads have names * accessible via {@link Thread#getName} of * <em>pool-N-thread-M</em>, where <em>N</em> is the sequence * number of this factory, and <em>M</em> is the sequence number * of the thread created by this factory. * * @param registry the {@link MetricRegistry} that will contain the metrics. * @param name the (metrics) name for this executor service, see {@link MetricRegistry#name(String, String...)}. * @return a thread factory * @see Executors#defaultThreadFactory() */ public static InstrumentedThreadFactory defaultThreadFactory(MetricRegistry registry, String name) { return new InstrumentedThreadFactory(Executors.defaultThreadFactory(), registry, name); } /** * Returns an instrumented default thread factory used to create new threads. * This factory creates all new threads used by an Executor in the * same {@link ThreadGroup}. If there is a {@link * java.lang.SecurityManager}, it uses the group of {@link * System#getSecurityManager}, else the group of the thread * invoking this {@code defaultThreadFactory} method. Each new * thread is created as a non-daemon thread with priority set to * the smaller of {@code Thread.NORM_PRIORITY} and the maximum * priority permitted in the thread group. New threads have names * accessible via {@link Thread#getName} of * <em>pool-N-thread-M</em>, where <em>N</em> is the sequence * number of this factory, and <em>M</em> is the sequence number * of the thread created by this factory. * * @param registry the {@link MetricRegistry} that will contain the metrics. * @return a thread factory * @see Executors#defaultThreadFactory() */ public static InstrumentedThreadFactory defaultThreadFactory(MetricRegistry registry) { return new InstrumentedThreadFactory(Executors.defaultThreadFactory(), registry); } /** * Returns an instrumented thread factory used to create new threads that * have the same permissions as the current thread. * <p> * This factory creates threads with the same settings as {@link * Executors#defaultThreadFactory}, additionally setting the * AccessControlContext and contextClassLoader of new threads to * be the same as the thread invoking this * {@code privilegedThreadFactory} method. A new * {@code privilegedThreadFactory} can be created within an * {@link java.security.AccessController#doPrivileged AccessController.doPrivileged} * action setting the current thread's access control context to * create threads with the selected permission settings holding * within that action. * </p> * <p>Note that while tasks running within such threads will have * the same access control and class loader settings as the * current thread, they need not have the same {@link * java.lang.ThreadLocal} or {@link * java.lang.InheritableThreadLocal} values. If necessary, * particular values of thread locals can be set or reset before * any task runs in {@link ThreadPoolExecutor} subclasses using * {@link ThreadPoolExecutor#beforeExecute(Thread, Runnable)}. * Also, if it is necessary to initialize worker threads to have * the same InheritableThreadLocal settings as some other * designated thread, you can create a custom ThreadFactory in * which that thread waits for and services requests to create * others that will inherit its values. * * @param registry the {@link MetricRegistry} that will contain the metrics. * @param name the (metrics) name for this executor service, see {@link MetricRegistry#name(String, String...)}. * @return a thread factory * @throws java.security.AccessControlException if the current access control * context does not have permission to both get and set context * class loader * @see Executors#privilegedThreadFactory() */ public static InstrumentedThreadFactory privilegedThreadFactory(MetricRegistry registry, String name) { return new InstrumentedThreadFactory(Executors.privilegedThreadFactory(), registry, name); } /** * Returns an instrumented thread factory used to create new threads that * have the same permissions as the current thread. * <p> * This factory creates threads with the same settings as {@link * Executors#defaultThreadFactory}, additionally setting the * AccessControlContext and contextClassLoader of new threads to * be the same as the thread invoking this * {@code privilegedThreadFactory} method. A new * {@code privilegedThreadFactory} can be created within an * {@link java.security.AccessController#doPrivileged AccessController.doPrivileged} * action setting the current thread's access control context to * create threads with the selected permission settings holding * within that action. * </p> * <p>Note that while tasks running within such threads will have * the same access control and class loader settings as the * current thread, they need not have the same {@link * java.lang.ThreadLocal} or {@link * java.lang.InheritableThreadLocal} values. If necessary, * particular values of thread locals can be set or reset before * any task runs in {@link ThreadPoolExecutor} subclasses using * {@link ThreadPoolExecutor#beforeExecute(Thread, Runnable)}. * Also, if it is necessary to initialize worker threads to have * the same InheritableThreadLocal settings as some other * designated thread, you can create a custom ThreadFactory in * which that thread waits for and services requests to create * others that will inherit its values. * * @param registry the {@link MetricRegistry} that will contain the metrics. * @return a thread factory * @throws java.security.AccessControlException if the current access control * context does not have permission to both get and set context * class loader * @see Executors#privilegedThreadFactory() */ public static InstrumentedThreadFactory privilegedThreadFactory(MetricRegistry registry) { return new InstrumentedThreadFactory(Executors.privilegedThreadFactory(), registry); } /** * Cannot instantiate. */ private InstrumentedExecutors() { } }