001/** 002 * Logback: the reliable, generic, fast and flexible logging framework. Copyright (C) 1999-2015, QOS.ch. All rights 003 * reserved. 004 * 005 * This program and the accompanying materials are dual-licensed under either the terms of the Eclipse Public License 006 * v1.0 as published by the Eclipse Foundation 007 * 008 * or (per the licensee's choosing) 009 * 010 * under the terms of the GNU Lesser General Public License version 2.1 as published by the Free Software Foundation. 011 */ 012package ch.qos.logback.core.util; 013 014import java.lang.reflect.InvocationTargetException; 015import java.lang.reflect.Method; 016import java.util.concurrent.*; 017import java.util.concurrent.atomic.AtomicInteger; 018 019import ch.qos.logback.core.CoreConstants; 020 021/** 022 * Static utility methods for manipulating an {@link ExecutorService}. 023 * 024 * @author Carl Harris 025 * @author Mikhail Mazursky 026 */ 027public class ExecutorServiceUtil { 028 029 private static final ThreadFactory THREAD_FACTORY_FOR_SCHEDULED_EXECUTION_SERVICE = new ThreadFactory() { 030 031 private final AtomicInteger threadNumber = new AtomicInteger(1); 032 033 private final ThreadFactory defaultFactory = makeThreadFactory(); 034 035 /** 036 * A thread factory which may be a virtual thread factory the JDK supports it. 037 * 038 * @return 039 */ 040 private ThreadFactory makeThreadFactory() { 041 return Executors.defaultThreadFactory(); 042 } 043 044 @Override 045 public Thread newThread(Runnable r) { 046 Thread thread = defaultFactory.newThread(r); 047 if (!thread.isDaemon()) { 048 thread.setDaemon(true); 049 } 050 thread.setName("logback-" + threadNumber.getAndIncrement()); 051 return thread; 052 } 053 }; 054 055 static public ScheduledExecutorService newScheduledExecutorService() { 056 return new ScheduledThreadPoolExecutor(CoreConstants.SCHEDULED_EXECUTOR_POOL_SIZE, THREAD_FACTORY_FOR_SCHEDULED_EXECUTION_SERVICE); 057 } 058 059 /** 060 * Creates an ThreadPoolExecutor suitable for use by logback components. 061 * 062 * @since 1.4.7 063 * @return ThreadPoolExecutor 064 */ 065 static public ThreadPoolExecutor newThreadPoolExecutor() { 066 067 // irrelevant parameter when LinkedBlockingQueue is in use 068 final int maximumPoolSize = CoreConstants.CORE_POOL_SIZE + 1; 069 final long keepAliveMillis = 100L; 070 071 // As of version 1.5.13, the SynchronousQueue was replaced by LinkedBlockingQueue 072 // This has the effect of queueing jobs immediately and have them run by CORE_POOL_SIZE 073 // threads. We expect jobs to arrive at a relatively slow pace compared to their duration. 074 // Note that threads are removed if idle more than keepAliveMillis 075 ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(CoreConstants.CORE_POOL_SIZE, maximumPoolSize, keepAliveMillis, TimeUnit.MILLISECONDS, 076 new LinkedBlockingQueue<>(), THREAD_FACTORY_FOR_SCHEDULED_EXECUTION_SERVICE); 077 threadPoolExecutor.allowCoreThreadTimeOut(true); 078 return threadPoolExecutor; 079 080 } 081 082 /** 083 * Shuts down an executor service. 084 * <p> 085 * 086 * @param executorService the executor service to shut down 087 */ 088 static public void shutdown(ExecutorService executorService) { 089 if (executorService != null) { 090 executorService.shutdownNow(); 091 } 092 } 093 094 /** 095 * An alternate implementation of {@link #newThreadPoolExecutor} which returns a virtual thread per task executor when 096 * available. 097 * 098 * @since 1.3.12/1.4.12 099 */ 100 static public ExecutorService newAlternateThreadPoolExecutor() { 101 return newThreadPoolExecutor(); 102 } 103}