Dropped threadpool arrays.

This commit is contained in:
MobiusDevelopment 2019-06-09 02:07:13 +00:00
parent f07e87d3df
commit 87d7a61fc6
56 changed files with 1131 additions and 2042 deletions

View File

@ -126,24 +126,16 @@ ServerListBrackets = False
# Thread Configuration
# ---------------------------------------------------------------------------
# Determines the amount of scheduled thread pools. If set to -1, the server will decide the amount depending on the available processors.
# Default: -1
ScheduledThreadPoolCount = -1
# Specifies how many threads will be in the scheduled pool.
# Default: 40
ScheduledThreadPoolCount = 40
# Specifies how many threads will be in a single scheduled pool.
# Default: 4
ThreadsPerScheduledThreadPool = 4
# Specifies how many threads will be in the single instant pool.
# Default: 20
InstantThreadPoolCount = 20
# Determines the amount of instant thread pools. If set to -1, the server will decide the amount depending on the available processors.
# Default: -1
InstantThreadPoolCount = -1
# Specifies how many threads will be in a single instant pool.
# Default: 2
ThreadsPerInstantThreadPool = 2
# Default: 2
UrgentPacketThreadCoreSize = 2
# Default: 20
UrgentPacketThreadCoreSize = 20
# Use threads to decrease startup time.
# Default: False

View File

@ -428,9 +428,7 @@ public final class Config
public static boolean ALT_DEV_SHOW_QUESTS_LOAD_IN_LOGS;
public static boolean ALT_DEV_SHOW_SCRIPTS_LOAD_IN_LOGS;
public static int SCHEDULED_THREAD_POOL_COUNT;
public static int THREADS_PER_SCHEDULED_THREAD_POOL;
public static int INSTANT_THREAD_POOL_COUNT;
public static int THREADS_PER_INSTANT_THREAD_POOL;
public static int IO_PACKET_THREAD_CORE_SIZE;
public static boolean THREADS_FOR_LOADING;
public static boolean DEADLOCK_DETECTOR;
@ -1352,19 +1350,9 @@ public final class Config
SERVER_LIST_AGE = serverSettings.getInt("ServerListAge", 0);
SERVER_LIST_BRACKET = serverSettings.getBoolean("ServerListBrackets", false);
SCHEDULED_THREAD_POOL_COUNT = serverSettings.getInt("ScheduledThreadPoolCount", -1);
if (SCHEDULED_THREAD_POOL_COUNT == -1)
{
SCHEDULED_THREAD_POOL_COUNT = Runtime.getRuntime().availableProcessors();
}
THREADS_PER_SCHEDULED_THREAD_POOL = serverSettings.getInt("ThreadsPerScheduledThreadPool", 4);
INSTANT_THREAD_POOL_COUNT = serverSettings.getInt("InstantThreadPoolCount", -1);
if (INSTANT_THREAD_POOL_COUNT == -1)
{
INSTANT_THREAD_POOL_COUNT = Runtime.getRuntime().availableProcessors();
}
THREADS_PER_INSTANT_THREAD_POOL = serverSettings.getInt("ThreadsPerInstantThreadPool", 2);
IO_PACKET_THREAD_CORE_SIZE = serverSettings.getInt("UrgentPacketThreadCoreSize", 2);
SCHEDULED_THREAD_POOL_COUNT = serverSettings.getInt("ScheduledThreadPoolCount", 40);
INSTANT_THREAD_POOL_COUNT = serverSettings.getInt("InstantThreadPoolCount", 20);
IO_PACKET_THREAD_CORE_SIZE = serverSettings.getInt("UrgentPacketThreadCoreSize", 20);
THREADS_FOR_LOADING = serverSettings.getBoolean("ThreadsForLoading", false);
DEADLOCK_DETECTOR = serverSettings.getBoolean("DeadLockDetector", true);

View File

@ -16,13 +16,17 @@
*/
package org.l2jmobius.commons.concurrent;
import java.lang.Thread.UncaughtExceptionHandler;
import java.util.logging.Logger;
import org.l2jmobius.Config;
/**
* @author UnAfraid
* @author Mobius
*/
public final class RunnableWrapper implements Runnable
{
private static final Logger LOGGER = Logger.getLogger(RunnableWrapper.class.getName());
private final Runnable _runnable;
public RunnableWrapper(Runnable runnable)
@ -37,14 +41,9 @@ public final class RunnableWrapper implements Runnable
{
_runnable.run();
}
catch (Throwable e)
catch (Exception e)
{
final Thread t = Thread.currentThread();
final UncaughtExceptionHandler h = t.getUncaughtExceptionHandler();
if (h != null)
{
h.uncaughtException(t, e);
}
LOGGER.warning(e.getMessage() + Config.EOL + e.getStackTrace());
}
}
}

View File

@ -26,10 +26,9 @@ import java.util.logging.Logger;
import org.l2jmobius.Config;
/**
* This class handles thread pooling system. It relies on two ThreadPoolExecutor arrays, which poolers number is generated using config.
* <p>
* Those arrays hold following pools:
* </p>
* This class handles thread pooling system.<br>
* It relies on two threadpool executors, which pool size is set using config.<br>
* Those arrays hold following pools:<br>
* <ul>
* <li>Scheduled pool keeps a track about incoming, future events.</li>
* <li>Instant pool handles short-life events.</li>
@ -39,59 +38,33 @@ public final class ThreadPool
{
private static final Logger LOGGER = Logger.getLogger(ThreadPool.class.getName());
private static ScheduledThreadPoolExecutor[] SCHEDULED_POOLS = new ScheduledThreadPoolExecutor[Config.SCHEDULED_THREAD_POOL_COUNT];
private static ThreadPoolExecutor[] INSTANT_POOLS = new ThreadPoolExecutor[Config.INSTANT_THREAD_POOL_COUNT];
private static volatile int SCHEDULED_THREAD_RANDOMIZER = 0;
private static volatile int INSTANT_THREAD_RANDOMIZER = 0;
private static final ScheduledThreadPoolExecutor SCHEDULED_POOL = new ScheduledThreadPoolExecutor(Config.SCHEDULED_THREAD_POOL_COUNT);
private static final ThreadPoolExecutor INSTANT_POOL = new ThreadPoolExecutor(Config.INSTANT_THREAD_POOL_COUNT, Config.INSTANT_THREAD_POOL_COUNT, 0, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(100000));
public static void init()
{
// Feed scheduled pool.
for (int i = 0; i < Config.SCHEDULED_THREAD_POOL_COUNT; i++)
{
SCHEDULED_POOLS[i] = new ScheduledThreadPoolExecutor(Config.THREADS_PER_SCHEDULED_THREAD_POOL);
}
// Feed instant pool.
for (int i = 0; i < Config.INSTANT_THREAD_POOL_COUNT; i++)
{
INSTANT_POOLS[i] = new ThreadPoolExecutor(Config.THREADS_PER_INSTANT_THREAD_POOL, Config.THREADS_PER_INSTANT_THREAD_POOL, 0, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(100000));
}
// Prestart core threads.
for (ScheduledThreadPoolExecutor threadPool : SCHEDULED_POOLS)
{
threadPool.setRejectedExecutionHandler(new RejectedExecutionHandlerImpl());
threadPool.setRemoveOnCancelPolicy(true);
threadPool.prestartAllCoreThreads();
}
for (ThreadPoolExecutor threadPool : INSTANT_POOLS)
{
threadPool.setRejectedExecutionHandler(new RejectedExecutionHandlerImpl());
threadPool.prestartAllCoreThreads();
}
// Set pool options.
SCHEDULED_POOL.setRejectedExecutionHandler(new RejectedExecutionHandlerImpl());
SCHEDULED_POOL.setRemoveOnCancelPolicy(true);
SCHEDULED_POOL.prestartAllCoreThreads();
INSTANT_POOL.setRejectedExecutionHandler(new RejectedExecutionHandlerImpl());
INSTANT_POOL.prestartAllCoreThreads();
// Launch purge task.
scheduleAtFixedRate(() ->
{
purge();
}, 600000, 600000);
}, 60000, 60000);
LOGGER.info("ThreadPool: Initialized");
LOGGER.info("..." + Config.SCHEDULED_THREAD_POOL_COUNT + " scheduled pool executors with " + (Config.SCHEDULED_THREAD_POOL_COUNT * Config.THREADS_PER_SCHEDULED_THREAD_POOL) + " total threads.");
LOGGER.info("..." + Config.INSTANT_THREAD_POOL_COUNT + " instant pool executors with " + (Config.INSTANT_THREAD_POOL_COUNT * Config.THREADS_PER_INSTANT_THREAD_POOL) + " total threads.");
LOGGER.info("...scheduled pool executor with " + Config.SCHEDULED_THREAD_POOL_COUNT + " total threads.");
LOGGER.info("...instant pool executor with " + Config.INSTANT_THREAD_POOL_COUNT + " total threads.");
}
public static void purge()
{
for (ScheduledThreadPoolExecutor threadPool : SCHEDULED_POOLS)
{
threadPool.purge();
}
for (ThreadPoolExecutor threadPool : INSTANT_POOLS)
{
threadPool.purge();
}
SCHEDULED_POOL.purge();
INSTANT_POOL.purge();
}
/**
@ -102,16 +75,14 @@ public final class ThreadPool
*/
public static ScheduledFuture<?> schedule(Runnable runnable, long delay)
{
synchronized (SCHEDULED_POOLS)
try
{
try
{
return SCHEDULED_POOLS[SCHEDULED_THREAD_RANDOMIZER++ % Config.SCHEDULED_THREAD_POOL_COUNT].schedule(new RunnableWrapper(runnable), delay, TimeUnit.MILLISECONDS);
}
catch (Exception e)
{
return null;
}
return SCHEDULED_POOL.schedule(new RunnableWrapper(runnable), delay, TimeUnit.MILLISECONDS);
}
catch (Exception e)
{
LOGGER.warning(e.getMessage() + Config.EOL + e.getStackTrace());
return null;
}
}
@ -124,16 +95,14 @@ public final class ThreadPool
*/
public static ScheduledFuture<?> scheduleAtFixedRate(Runnable runnable, long initialDelay, long period)
{
synchronized (SCHEDULED_POOLS)
try
{
try
{
return SCHEDULED_POOLS[SCHEDULED_THREAD_RANDOMIZER++ % Config.SCHEDULED_THREAD_POOL_COUNT].scheduleAtFixedRate(new RunnableWrapper(runnable), initialDelay, period, TimeUnit.MILLISECONDS);
}
catch (Exception e)
{
return null;
}
return SCHEDULED_POOL.scheduleAtFixedRate(new RunnableWrapper(runnable), initialDelay, period, TimeUnit.MILLISECONDS);
}
catch (Exception e)
{
LOGGER.warning(e.getMessage() + Config.EOL + e.getStackTrace());
return null;
}
}
@ -143,50 +112,43 @@ public final class ThreadPool
*/
public static void execute(Runnable runnable)
{
synchronized (INSTANT_POOLS)
try
{
try
{
INSTANT_POOLS[INSTANT_THREAD_RANDOMIZER++ % Config.INSTANT_THREAD_POOL_COUNT].execute(new RunnableWrapper(runnable));
}
catch (Exception e)
{
}
INSTANT_POOL.execute(new RunnableWrapper(runnable));
}
catch (Exception e)
{
LOGGER.warning(e.getMessage() + Config.EOL + e.getStackTrace());
}
}
public static String[] getStats()
{
final String[] stats = new String[(SCHEDULED_POOLS.length + INSTANT_POOLS.length) * 10];
final String[] stats = new String[20];
int pos = 0;
for (int i = 0; i < SCHEDULED_POOLS.length; i++)
{
final ScheduledThreadPoolExecutor threadPool = SCHEDULED_POOLS[i];
stats[pos++] = "Scheduled pool #" + i + ":";
stats[pos++] = " |- ActiveCount: ...... " + threadPool.getActiveCount();
stats[pos++] = " |- CorePoolSize: ..... " + threadPool.getCorePoolSize();
stats[pos++] = " |- PoolSize: ......... " + threadPool.getPoolSize();
stats[pos++] = " |- LargestPoolSize: .. " + threadPool.getLargestPoolSize();
stats[pos++] = " |- MaximumPoolSize: .. " + threadPool.getMaximumPoolSize();
stats[pos++] = " |- CompletedTaskCount: " + threadPool.getCompletedTaskCount();
stats[pos++] = " |- QueuedTaskCount: .. " + threadPool.getQueue().size();
stats[pos++] = " |- TaskCount: ........ " + threadPool.getTaskCount();
stats[pos++] = " | -------";
}
for (int i = 0; i < INSTANT_POOLS.length; i++)
{
final ThreadPoolExecutor threadPool = INSTANT_POOLS[i];
stats[pos++] = "Instant pool #" + i + ":";
stats[pos++] = " |- ActiveCount: ...... " + threadPool.getActiveCount();
stats[pos++] = " |- CorePoolSize: ..... " + threadPool.getCorePoolSize();
stats[pos++] = " |- PoolSize: ......... " + threadPool.getPoolSize();
stats[pos++] = " |- LargestPoolSize: .. " + threadPool.getLargestPoolSize();
stats[pos++] = " |- MaximumPoolSize: .. " + threadPool.getMaximumPoolSize();
stats[pos++] = " |- CompletedTaskCount: " + threadPool.getCompletedTaskCount();
stats[pos++] = " |- QueuedTaskCount: .. " + threadPool.getQueue().size();
stats[pos++] = " |- TaskCount: ........ " + threadPool.getTaskCount();
stats[pos++] = " | -------";
}
stats[pos++] = "Scheduled pool:";
stats[pos++] = " |- ActiveCount: ...... " + SCHEDULED_POOL.getActiveCount();
stats[pos++] = " |- CorePoolSize: ..... " + SCHEDULED_POOL.getCorePoolSize();
stats[pos++] = " |- PoolSize: ......... " + SCHEDULED_POOL.getPoolSize();
stats[pos++] = " |- LargestPoolSize: .. " + SCHEDULED_POOL.getLargestPoolSize();
stats[pos++] = " |- MaximumPoolSize: .. " + SCHEDULED_POOL.getMaximumPoolSize();
stats[pos++] = " |- CompletedTaskCount: " + SCHEDULED_POOL.getCompletedTaskCount();
stats[pos++] = " |- QueuedTaskCount: .. " + SCHEDULED_POOL.getQueue().size();
stats[pos++] = " |- TaskCount: ........ " + SCHEDULED_POOL.getTaskCount();
stats[pos++] = " | -------";
stats[pos++] = "Instant pool:";
stats[pos++] = " |- ActiveCount: ...... " + INSTANT_POOL.getActiveCount();
stats[pos++] = " |- CorePoolSize: ..... " + INSTANT_POOL.getCorePoolSize();
stats[pos++] = " |- PoolSize: ......... " + INSTANT_POOL.getPoolSize();
stats[pos++] = " |- LargestPoolSize: .. " + INSTANT_POOL.getLargestPoolSize();
stats[pos++] = " |- MaximumPoolSize: .. " + INSTANT_POOL.getMaximumPoolSize();
stats[pos++] = " |- CompletedTaskCount: " + INSTANT_POOL.getCompletedTaskCount();
stats[pos++] = " |- QueuedTaskCount: .. " + INSTANT_POOL.getQueue().size();
stats[pos++] = " |- TaskCount: ........ " + INSTANT_POOL.getTaskCount();
stats[pos++] = " | -------";
return stats;
}
@ -198,14 +160,8 @@ public final class ThreadPool
try
{
LOGGER.info("ThreadPool: Shutting down.");
for (ScheduledThreadPoolExecutor threadPool : SCHEDULED_POOLS)
{
threadPool.shutdownNow();
}
for (ThreadPoolExecutor threadPool : INSTANT_POOLS)
{
threadPool.shutdownNow();
}
SCHEDULED_POOL.shutdownNow();
INSTANT_POOL.shutdownNow();
}
catch (Throwable t)
{

View File

@ -126,24 +126,16 @@ ServerListBrackets = False
# Thread Configuration
# ---------------------------------------------------------------------------
# Determines the amount of scheduled thread pools. If set to -1, the server will decide the amount depending on the available processors.
# Default: -1
ScheduledThreadPoolCount = -1
# Specifies how many threads will be in the scheduled pool.
# Default: 40
ScheduledThreadPoolCount = 40
# Specifies how many threads will be in a single scheduled pool.
# Default: 4
ThreadsPerScheduledThreadPool = 4
# Specifies how many threads will be in the single instant pool.
# Default: 20
InstantThreadPoolCount = 20
# Determines the amount of instant thread pools. If set to -1, the server will decide the amount depending on the available processors.
# Default: -1
InstantThreadPoolCount = -1
# Specifies how many threads will be in a single instant pool.
# Default: 2
ThreadsPerInstantThreadPool = 2
# Default: 2
UrgentPacketThreadCoreSize = 2
# Default: 20
UrgentPacketThreadCoreSize = 20
# Use threads to decrease startup time.
# Default: False

View File

@ -434,9 +434,7 @@ public final class Config
public static boolean ALT_DEV_SHOW_QUESTS_LOAD_IN_LOGS;
public static boolean ALT_DEV_SHOW_SCRIPTS_LOAD_IN_LOGS;
public static int SCHEDULED_THREAD_POOL_COUNT;
public static int THREADS_PER_SCHEDULED_THREAD_POOL;
public static int INSTANT_THREAD_POOL_COUNT;
public static int THREADS_PER_INSTANT_THREAD_POOL;
public static int IO_PACKET_THREAD_CORE_SIZE;
public static boolean THREADS_FOR_LOADING;
public static boolean DEADLOCK_DETECTOR;
@ -1359,19 +1357,9 @@ public final class Config
SERVER_LIST_AGE = serverSettings.getInt("ServerListAge", 0);
SERVER_LIST_BRACKET = serverSettings.getBoolean("ServerListBrackets", false);
SCHEDULED_THREAD_POOL_COUNT = serverSettings.getInt("ScheduledThreadPoolCount", -1);
if (SCHEDULED_THREAD_POOL_COUNT == -1)
{
SCHEDULED_THREAD_POOL_COUNT = Runtime.getRuntime().availableProcessors();
}
THREADS_PER_SCHEDULED_THREAD_POOL = serverSettings.getInt("ThreadsPerScheduledThreadPool", 4);
INSTANT_THREAD_POOL_COUNT = serverSettings.getInt("InstantThreadPoolCount", -1);
if (INSTANT_THREAD_POOL_COUNT == -1)
{
INSTANT_THREAD_POOL_COUNT = Runtime.getRuntime().availableProcessors();
}
THREADS_PER_INSTANT_THREAD_POOL = serverSettings.getInt("ThreadsPerInstantThreadPool", 2);
IO_PACKET_THREAD_CORE_SIZE = serverSettings.getInt("UrgentPacketThreadCoreSize", 2);
SCHEDULED_THREAD_POOL_COUNT = serverSettings.getInt("ScheduledThreadPoolCount", 40);
INSTANT_THREAD_POOL_COUNT = serverSettings.getInt("InstantThreadPoolCount", 20);
IO_PACKET_THREAD_CORE_SIZE = serverSettings.getInt("UrgentPacketThreadCoreSize", 20);
THREADS_FOR_LOADING = serverSettings.getBoolean("ThreadsForLoading", false);
DEADLOCK_DETECTOR = serverSettings.getBoolean("DeadLockDetector", true);

View File

@ -16,13 +16,17 @@
*/
package org.l2jmobius.commons.concurrent;
import java.lang.Thread.UncaughtExceptionHandler;
import java.util.logging.Logger;
import org.l2jmobius.Config;
/**
* @author UnAfraid
* @author Mobius
*/
public final class RunnableWrapper implements Runnable
{
private static final Logger LOGGER = Logger.getLogger(RunnableWrapper.class.getName());
private final Runnable _runnable;
public RunnableWrapper(Runnable runnable)
@ -37,14 +41,9 @@ public final class RunnableWrapper implements Runnable
{
_runnable.run();
}
catch (Throwable e)
catch (Exception e)
{
final Thread t = Thread.currentThread();
final UncaughtExceptionHandler h = t.getUncaughtExceptionHandler();
if (h != null)
{
h.uncaughtException(t, e);
}
LOGGER.warning(e.getMessage() + Config.EOL + e.getStackTrace());
}
}
}

View File

@ -26,10 +26,9 @@ import java.util.logging.Logger;
import org.l2jmobius.Config;
/**
* This class handles thread pooling system. It relies on two ThreadPoolExecutor arrays, which poolers number is generated using config.
* <p>
* Those arrays hold following pools:
* </p>
* This class handles thread pooling system.<br>
* It relies on two threadpool executors, which pool size is set using config.<br>
* Those arrays hold following pools:<br>
* <ul>
* <li>Scheduled pool keeps a track about incoming, future events.</li>
* <li>Instant pool handles short-life events.</li>
@ -39,59 +38,33 @@ public final class ThreadPool
{
private static final Logger LOGGER = Logger.getLogger(ThreadPool.class.getName());
private static ScheduledThreadPoolExecutor[] SCHEDULED_POOLS = new ScheduledThreadPoolExecutor[Config.SCHEDULED_THREAD_POOL_COUNT];
private static ThreadPoolExecutor[] INSTANT_POOLS = new ThreadPoolExecutor[Config.INSTANT_THREAD_POOL_COUNT];
private static volatile int SCHEDULED_THREAD_RANDOMIZER = 0;
private static volatile int INSTANT_THREAD_RANDOMIZER = 0;
private static final ScheduledThreadPoolExecutor SCHEDULED_POOL = new ScheduledThreadPoolExecutor(Config.SCHEDULED_THREAD_POOL_COUNT);
private static final ThreadPoolExecutor INSTANT_POOL = new ThreadPoolExecutor(Config.INSTANT_THREAD_POOL_COUNT, Config.INSTANT_THREAD_POOL_COUNT, 0, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(100000));
public static void init()
{
// Feed scheduled pool.
for (int i = 0; i < Config.SCHEDULED_THREAD_POOL_COUNT; i++)
{
SCHEDULED_POOLS[i] = new ScheduledThreadPoolExecutor(Config.THREADS_PER_SCHEDULED_THREAD_POOL);
}
// Feed instant pool.
for (int i = 0; i < Config.INSTANT_THREAD_POOL_COUNT; i++)
{
INSTANT_POOLS[i] = new ThreadPoolExecutor(Config.THREADS_PER_INSTANT_THREAD_POOL, Config.THREADS_PER_INSTANT_THREAD_POOL, 0, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(100000));
}
// Prestart core threads.
for (ScheduledThreadPoolExecutor threadPool : SCHEDULED_POOLS)
{
threadPool.setRejectedExecutionHandler(new RejectedExecutionHandlerImpl());
threadPool.setRemoveOnCancelPolicy(true);
threadPool.prestartAllCoreThreads();
}
for (ThreadPoolExecutor threadPool : INSTANT_POOLS)
{
threadPool.setRejectedExecutionHandler(new RejectedExecutionHandlerImpl());
threadPool.prestartAllCoreThreads();
}
// Set pool options.
SCHEDULED_POOL.setRejectedExecutionHandler(new RejectedExecutionHandlerImpl());
SCHEDULED_POOL.setRemoveOnCancelPolicy(true);
SCHEDULED_POOL.prestartAllCoreThreads();
INSTANT_POOL.setRejectedExecutionHandler(new RejectedExecutionHandlerImpl());
INSTANT_POOL.prestartAllCoreThreads();
// Launch purge task.
scheduleAtFixedRate(() ->
{
purge();
}, 600000, 600000);
}, 60000, 60000);
LOGGER.info("ThreadPool: Initialized");
LOGGER.info("..." + Config.SCHEDULED_THREAD_POOL_COUNT + " scheduled pool executors with " + (Config.SCHEDULED_THREAD_POOL_COUNT * Config.THREADS_PER_SCHEDULED_THREAD_POOL) + " total threads.");
LOGGER.info("..." + Config.INSTANT_THREAD_POOL_COUNT + " instant pool executors with " + (Config.INSTANT_THREAD_POOL_COUNT * Config.THREADS_PER_INSTANT_THREAD_POOL) + " total threads.");
LOGGER.info("...scheduled pool executor with " + Config.SCHEDULED_THREAD_POOL_COUNT + " total threads.");
LOGGER.info("...instant pool executor with " + Config.INSTANT_THREAD_POOL_COUNT + " total threads.");
}
public static void purge()
{
for (ScheduledThreadPoolExecutor threadPool : SCHEDULED_POOLS)
{
threadPool.purge();
}
for (ThreadPoolExecutor threadPool : INSTANT_POOLS)
{
threadPool.purge();
}
SCHEDULED_POOL.purge();
INSTANT_POOL.purge();
}
/**
@ -102,16 +75,14 @@ public final class ThreadPool
*/
public static ScheduledFuture<?> schedule(Runnable runnable, long delay)
{
synchronized (SCHEDULED_POOLS)
try
{
try
{
return SCHEDULED_POOLS[SCHEDULED_THREAD_RANDOMIZER++ % Config.SCHEDULED_THREAD_POOL_COUNT].schedule(new RunnableWrapper(runnable), delay, TimeUnit.MILLISECONDS);
}
catch (Exception e)
{
return null;
}
return SCHEDULED_POOL.schedule(new RunnableWrapper(runnable), delay, TimeUnit.MILLISECONDS);
}
catch (Exception e)
{
LOGGER.warning(e.getMessage() + Config.EOL + e.getStackTrace());
return null;
}
}
@ -124,16 +95,14 @@ public final class ThreadPool
*/
public static ScheduledFuture<?> scheduleAtFixedRate(Runnable runnable, long initialDelay, long period)
{
synchronized (SCHEDULED_POOLS)
try
{
try
{
return SCHEDULED_POOLS[SCHEDULED_THREAD_RANDOMIZER++ % Config.SCHEDULED_THREAD_POOL_COUNT].scheduleAtFixedRate(new RunnableWrapper(runnable), initialDelay, period, TimeUnit.MILLISECONDS);
}
catch (Exception e)
{
return null;
}
return SCHEDULED_POOL.scheduleAtFixedRate(new RunnableWrapper(runnable), initialDelay, period, TimeUnit.MILLISECONDS);
}
catch (Exception e)
{
LOGGER.warning(e.getMessage() + Config.EOL + e.getStackTrace());
return null;
}
}
@ -143,50 +112,43 @@ public final class ThreadPool
*/
public static void execute(Runnable runnable)
{
synchronized (INSTANT_POOLS)
try
{
try
{
INSTANT_POOLS[INSTANT_THREAD_RANDOMIZER++ % Config.INSTANT_THREAD_POOL_COUNT].execute(new RunnableWrapper(runnable));
}
catch (Exception e)
{
}
INSTANT_POOL.execute(new RunnableWrapper(runnable));
}
catch (Exception e)
{
LOGGER.warning(e.getMessage() + Config.EOL + e.getStackTrace());
}
}
public static String[] getStats()
{
final String[] stats = new String[(SCHEDULED_POOLS.length + INSTANT_POOLS.length) * 10];
final String[] stats = new String[20];
int pos = 0;
for (int i = 0; i < SCHEDULED_POOLS.length; i++)
{
final ScheduledThreadPoolExecutor threadPool = SCHEDULED_POOLS[i];
stats[pos++] = "Scheduled pool #" + i + ":";
stats[pos++] = " |- ActiveCount: ...... " + threadPool.getActiveCount();
stats[pos++] = " |- CorePoolSize: ..... " + threadPool.getCorePoolSize();
stats[pos++] = " |- PoolSize: ......... " + threadPool.getPoolSize();
stats[pos++] = " |- LargestPoolSize: .. " + threadPool.getLargestPoolSize();
stats[pos++] = " |- MaximumPoolSize: .. " + threadPool.getMaximumPoolSize();
stats[pos++] = " |- CompletedTaskCount: " + threadPool.getCompletedTaskCount();
stats[pos++] = " |- QueuedTaskCount: .. " + threadPool.getQueue().size();
stats[pos++] = " |- TaskCount: ........ " + threadPool.getTaskCount();
stats[pos++] = " | -------";
}
for (int i = 0; i < INSTANT_POOLS.length; i++)
{
final ThreadPoolExecutor threadPool = INSTANT_POOLS[i];
stats[pos++] = "Instant pool #" + i + ":";
stats[pos++] = " |- ActiveCount: ...... " + threadPool.getActiveCount();
stats[pos++] = " |- CorePoolSize: ..... " + threadPool.getCorePoolSize();
stats[pos++] = " |- PoolSize: ......... " + threadPool.getPoolSize();
stats[pos++] = " |- LargestPoolSize: .. " + threadPool.getLargestPoolSize();
stats[pos++] = " |- MaximumPoolSize: .. " + threadPool.getMaximumPoolSize();
stats[pos++] = " |- CompletedTaskCount: " + threadPool.getCompletedTaskCount();
stats[pos++] = " |- QueuedTaskCount: .. " + threadPool.getQueue().size();
stats[pos++] = " |- TaskCount: ........ " + threadPool.getTaskCount();
stats[pos++] = " | -------";
}
stats[pos++] = "Scheduled pool:";
stats[pos++] = " |- ActiveCount: ...... " + SCHEDULED_POOL.getActiveCount();
stats[pos++] = " |- CorePoolSize: ..... " + SCHEDULED_POOL.getCorePoolSize();
stats[pos++] = " |- PoolSize: ......... " + SCHEDULED_POOL.getPoolSize();
stats[pos++] = " |- LargestPoolSize: .. " + SCHEDULED_POOL.getLargestPoolSize();
stats[pos++] = " |- MaximumPoolSize: .. " + SCHEDULED_POOL.getMaximumPoolSize();
stats[pos++] = " |- CompletedTaskCount: " + SCHEDULED_POOL.getCompletedTaskCount();
stats[pos++] = " |- QueuedTaskCount: .. " + SCHEDULED_POOL.getQueue().size();
stats[pos++] = " |- TaskCount: ........ " + SCHEDULED_POOL.getTaskCount();
stats[pos++] = " | -------";
stats[pos++] = "Instant pool:";
stats[pos++] = " |- ActiveCount: ...... " + INSTANT_POOL.getActiveCount();
stats[pos++] = " |- CorePoolSize: ..... " + INSTANT_POOL.getCorePoolSize();
stats[pos++] = " |- PoolSize: ......... " + INSTANT_POOL.getPoolSize();
stats[pos++] = " |- LargestPoolSize: .. " + INSTANT_POOL.getLargestPoolSize();
stats[pos++] = " |- MaximumPoolSize: .. " + INSTANT_POOL.getMaximumPoolSize();
stats[pos++] = " |- CompletedTaskCount: " + INSTANT_POOL.getCompletedTaskCount();
stats[pos++] = " |- QueuedTaskCount: .. " + INSTANT_POOL.getQueue().size();
stats[pos++] = " |- TaskCount: ........ " + INSTANT_POOL.getTaskCount();
stats[pos++] = " | -------";
return stats;
}
@ -198,14 +160,8 @@ public final class ThreadPool
try
{
LOGGER.info("ThreadPool: Shutting down.");
for (ScheduledThreadPoolExecutor threadPool : SCHEDULED_POOLS)
{
threadPool.shutdownNow();
}
for (ThreadPoolExecutor threadPool : INSTANT_POOLS)
{
threadPool.shutdownNow();
}
SCHEDULED_POOL.shutdownNow();
INSTANT_POOL.shutdownNow();
}
catch (Throwable t)
{

View File

@ -126,24 +126,16 @@ ServerListBrackets = False
# Thread Configuration
# ---------------------------------------------------------------------------
# Determines the amount of scheduled thread pools. If set to -1, the server will decide the amount depending on the available processors.
# Default: -1
ScheduledThreadPoolCount = -1
# Specifies how many threads will be in the scheduled pool.
# Default: 40
ScheduledThreadPoolCount = 40
# Specifies how many threads will be in a single scheduled pool.
# Default: 4
ThreadsPerScheduledThreadPool = 4
# Specifies how many threads will be in the single instant pool.
# Default: 20
InstantThreadPoolCount = 20
# Determines the amount of instant thread pools. If set to -1, the server will decide the amount depending on the available processors.
# Default: -1
InstantThreadPoolCount = -1
# Specifies how many threads will be in a single instant pool.
# Default: 2
ThreadsPerInstantThreadPool = 2
# Default: 2
UrgentPacketThreadCoreSize = 2
# Default: 20
UrgentPacketThreadCoreSize = 20
# Use threads to decrease startup time.
# Default: False

View File

@ -434,9 +434,7 @@ public final class Config
public static boolean ALT_DEV_SHOW_QUESTS_LOAD_IN_LOGS;
public static boolean ALT_DEV_SHOW_SCRIPTS_LOAD_IN_LOGS;
public static int SCHEDULED_THREAD_POOL_COUNT;
public static int THREADS_PER_SCHEDULED_THREAD_POOL;
public static int INSTANT_THREAD_POOL_COUNT;
public static int THREADS_PER_INSTANT_THREAD_POOL;
public static int IO_PACKET_THREAD_CORE_SIZE;
public static boolean THREADS_FOR_LOADING;
public static boolean DEADLOCK_DETECTOR;
@ -1367,19 +1365,9 @@ public final class Config
SERVER_LIST_AGE = serverSettings.getInt("ServerListAge", 0);
SERVER_LIST_BRACKET = serverSettings.getBoolean("ServerListBrackets", false);
SCHEDULED_THREAD_POOL_COUNT = serverSettings.getInt("ScheduledThreadPoolCount", -1);
if (SCHEDULED_THREAD_POOL_COUNT == -1)
{
SCHEDULED_THREAD_POOL_COUNT = Runtime.getRuntime().availableProcessors();
}
THREADS_PER_SCHEDULED_THREAD_POOL = serverSettings.getInt("ThreadsPerScheduledThreadPool", 4);
INSTANT_THREAD_POOL_COUNT = serverSettings.getInt("InstantThreadPoolCount", -1);
if (INSTANT_THREAD_POOL_COUNT == -1)
{
INSTANT_THREAD_POOL_COUNT = Runtime.getRuntime().availableProcessors();
}
THREADS_PER_INSTANT_THREAD_POOL = serverSettings.getInt("ThreadsPerInstantThreadPool", 2);
IO_PACKET_THREAD_CORE_SIZE = serverSettings.getInt("UrgentPacketThreadCoreSize", 2);
SCHEDULED_THREAD_POOL_COUNT = serverSettings.getInt("ScheduledThreadPoolCount", 40);
INSTANT_THREAD_POOL_COUNT = serverSettings.getInt("InstantThreadPoolCount", 20);
IO_PACKET_THREAD_CORE_SIZE = serverSettings.getInt("UrgentPacketThreadCoreSize", 20);
THREADS_FOR_LOADING = serverSettings.getBoolean("ThreadsForLoading", false);
DEADLOCK_DETECTOR = serverSettings.getBoolean("DeadLockDetector", true);

View File

@ -16,13 +16,17 @@
*/
package org.l2jmobius.commons.concurrent;
import java.lang.Thread.UncaughtExceptionHandler;
import java.util.logging.Logger;
import org.l2jmobius.Config;
/**
* @author UnAfraid
* @author Mobius
*/
public final class RunnableWrapper implements Runnable
{
private static final Logger LOGGER = Logger.getLogger(RunnableWrapper.class.getName());
private final Runnable _runnable;
public RunnableWrapper(Runnable runnable)
@ -37,14 +41,9 @@ public final class RunnableWrapper implements Runnable
{
_runnable.run();
}
catch (Throwable e)
catch (Exception e)
{
final Thread t = Thread.currentThread();
final UncaughtExceptionHandler h = t.getUncaughtExceptionHandler();
if (h != null)
{
h.uncaughtException(t, e);
}
LOGGER.warning(e.getMessage() + Config.EOL + e.getStackTrace());
}
}
}

View File

@ -26,10 +26,9 @@ import java.util.logging.Logger;
import org.l2jmobius.Config;
/**
* This class handles thread pooling system. It relies on two ThreadPoolExecutor arrays, which poolers number is generated using config.
* <p>
* Those arrays hold following pools:
* </p>
* This class handles thread pooling system.<br>
* It relies on two threadpool executors, which pool size is set using config.<br>
* Those arrays hold following pools:<br>
* <ul>
* <li>Scheduled pool keeps a track about incoming, future events.</li>
* <li>Instant pool handles short-life events.</li>
@ -39,59 +38,33 @@ public final class ThreadPool
{
private static final Logger LOGGER = Logger.getLogger(ThreadPool.class.getName());
private static ScheduledThreadPoolExecutor[] SCHEDULED_POOLS = new ScheduledThreadPoolExecutor[Config.SCHEDULED_THREAD_POOL_COUNT];
private static ThreadPoolExecutor[] INSTANT_POOLS = new ThreadPoolExecutor[Config.INSTANT_THREAD_POOL_COUNT];
private static volatile int SCHEDULED_THREAD_RANDOMIZER = 0;
private static volatile int INSTANT_THREAD_RANDOMIZER = 0;
private static final ScheduledThreadPoolExecutor SCHEDULED_POOL = new ScheduledThreadPoolExecutor(Config.SCHEDULED_THREAD_POOL_COUNT);
private static final ThreadPoolExecutor INSTANT_POOL = new ThreadPoolExecutor(Config.INSTANT_THREAD_POOL_COUNT, Config.INSTANT_THREAD_POOL_COUNT, 0, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(100000));
public static void init()
{
// Feed scheduled pool.
for (int i = 0; i < Config.SCHEDULED_THREAD_POOL_COUNT; i++)
{
SCHEDULED_POOLS[i] = new ScheduledThreadPoolExecutor(Config.THREADS_PER_SCHEDULED_THREAD_POOL);
}
// Feed instant pool.
for (int i = 0; i < Config.INSTANT_THREAD_POOL_COUNT; i++)
{
INSTANT_POOLS[i] = new ThreadPoolExecutor(Config.THREADS_PER_INSTANT_THREAD_POOL, Config.THREADS_PER_INSTANT_THREAD_POOL, 0, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(100000));
}
// Prestart core threads.
for (ScheduledThreadPoolExecutor threadPool : SCHEDULED_POOLS)
{
threadPool.setRejectedExecutionHandler(new RejectedExecutionHandlerImpl());
threadPool.setRemoveOnCancelPolicy(true);
threadPool.prestartAllCoreThreads();
}
for (ThreadPoolExecutor threadPool : INSTANT_POOLS)
{
threadPool.setRejectedExecutionHandler(new RejectedExecutionHandlerImpl());
threadPool.prestartAllCoreThreads();
}
// Set pool options.
SCHEDULED_POOL.setRejectedExecutionHandler(new RejectedExecutionHandlerImpl());
SCHEDULED_POOL.setRemoveOnCancelPolicy(true);
SCHEDULED_POOL.prestartAllCoreThreads();
INSTANT_POOL.setRejectedExecutionHandler(new RejectedExecutionHandlerImpl());
INSTANT_POOL.prestartAllCoreThreads();
// Launch purge task.
scheduleAtFixedRate(() ->
{
purge();
}, 600000, 600000);
}, 60000, 60000);
LOGGER.info("ThreadPool: Initialized");
LOGGER.info("..." + Config.SCHEDULED_THREAD_POOL_COUNT + " scheduled pool executors with " + (Config.SCHEDULED_THREAD_POOL_COUNT * Config.THREADS_PER_SCHEDULED_THREAD_POOL) + " total threads.");
LOGGER.info("..." + Config.INSTANT_THREAD_POOL_COUNT + " instant pool executors with " + (Config.INSTANT_THREAD_POOL_COUNT * Config.THREADS_PER_INSTANT_THREAD_POOL) + " total threads.");
LOGGER.info("...scheduled pool executor with " + Config.SCHEDULED_THREAD_POOL_COUNT + " total threads.");
LOGGER.info("...instant pool executor with " + Config.INSTANT_THREAD_POOL_COUNT + " total threads.");
}
public static void purge()
{
for (ScheduledThreadPoolExecutor threadPool : SCHEDULED_POOLS)
{
threadPool.purge();
}
for (ThreadPoolExecutor threadPool : INSTANT_POOLS)
{
threadPool.purge();
}
SCHEDULED_POOL.purge();
INSTANT_POOL.purge();
}
/**
@ -102,16 +75,14 @@ public final class ThreadPool
*/
public static ScheduledFuture<?> schedule(Runnable runnable, long delay)
{
synchronized (SCHEDULED_POOLS)
try
{
try
{
return SCHEDULED_POOLS[SCHEDULED_THREAD_RANDOMIZER++ % Config.SCHEDULED_THREAD_POOL_COUNT].schedule(new RunnableWrapper(runnable), delay, TimeUnit.MILLISECONDS);
}
catch (Exception e)
{
return null;
}
return SCHEDULED_POOL.schedule(new RunnableWrapper(runnable), delay, TimeUnit.MILLISECONDS);
}
catch (Exception e)
{
LOGGER.warning(e.getMessage() + Config.EOL + e.getStackTrace());
return null;
}
}
@ -124,16 +95,14 @@ public final class ThreadPool
*/
public static ScheduledFuture<?> scheduleAtFixedRate(Runnable runnable, long initialDelay, long period)
{
synchronized (SCHEDULED_POOLS)
try
{
try
{
return SCHEDULED_POOLS[SCHEDULED_THREAD_RANDOMIZER++ % Config.SCHEDULED_THREAD_POOL_COUNT].scheduleAtFixedRate(new RunnableWrapper(runnable), initialDelay, period, TimeUnit.MILLISECONDS);
}
catch (Exception e)
{
return null;
}
return SCHEDULED_POOL.scheduleAtFixedRate(new RunnableWrapper(runnable), initialDelay, period, TimeUnit.MILLISECONDS);
}
catch (Exception e)
{
LOGGER.warning(e.getMessage() + Config.EOL + e.getStackTrace());
return null;
}
}
@ -143,50 +112,43 @@ public final class ThreadPool
*/
public static void execute(Runnable runnable)
{
synchronized (INSTANT_POOLS)
try
{
try
{
INSTANT_POOLS[INSTANT_THREAD_RANDOMIZER++ % Config.INSTANT_THREAD_POOL_COUNT].execute(new RunnableWrapper(runnable));
}
catch (Exception e)
{
}
INSTANT_POOL.execute(new RunnableWrapper(runnable));
}
catch (Exception e)
{
LOGGER.warning(e.getMessage() + Config.EOL + e.getStackTrace());
}
}
public static String[] getStats()
{
final String[] stats = new String[(SCHEDULED_POOLS.length + INSTANT_POOLS.length) * 10];
final String[] stats = new String[20];
int pos = 0;
for (int i = 0; i < SCHEDULED_POOLS.length; i++)
{
final ScheduledThreadPoolExecutor threadPool = SCHEDULED_POOLS[i];
stats[pos++] = "Scheduled pool #" + i + ":";
stats[pos++] = " |- ActiveCount: ...... " + threadPool.getActiveCount();
stats[pos++] = " |- CorePoolSize: ..... " + threadPool.getCorePoolSize();
stats[pos++] = " |- PoolSize: ......... " + threadPool.getPoolSize();
stats[pos++] = " |- LargestPoolSize: .. " + threadPool.getLargestPoolSize();
stats[pos++] = " |- MaximumPoolSize: .. " + threadPool.getMaximumPoolSize();
stats[pos++] = " |- CompletedTaskCount: " + threadPool.getCompletedTaskCount();
stats[pos++] = " |- QueuedTaskCount: .. " + threadPool.getQueue().size();
stats[pos++] = " |- TaskCount: ........ " + threadPool.getTaskCount();
stats[pos++] = " | -------";
}
for (int i = 0; i < INSTANT_POOLS.length; i++)
{
final ThreadPoolExecutor threadPool = INSTANT_POOLS[i];
stats[pos++] = "Instant pool #" + i + ":";
stats[pos++] = " |- ActiveCount: ...... " + threadPool.getActiveCount();
stats[pos++] = " |- CorePoolSize: ..... " + threadPool.getCorePoolSize();
stats[pos++] = " |- PoolSize: ......... " + threadPool.getPoolSize();
stats[pos++] = " |- LargestPoolSize: .. " + threadPool.getLargestPoolSize();
stats[pos++] = " |- MaximumPoolSize: .. " + threadPool.getMaximumPoolSize();
stats[pos++] = " |- CompletedTaskCount: " + threadPool.getCompletedTaskCount();
stats[pos++] = " |- QueuedTaskCount: .. " + threadPool.getQueue().size();
stats[pos++] = " |- TaskCount: ........ " + threadPool.getTaskCount();
stats[pos++] = " | -------";
}
stats[pos++] = "Scheduled pool:";
stats[pos++] = " |- ActiveCount: ...... " + SCHEDULED_POOL.getActiveCount();
stats[pos++] = " |- CorePoolSize: ..... " + SCHEDULED_POOL.getCorePoolSize();
stats[pos++] = " |- PoolSize: ......... " + SCHEDULED_POOL.getPoolSize();
stats[pos++] = " |- LargestPoolSize: .. " + SCHEDULED_POOL.getLargestPoolSize();
stats[pos++] = " |- MaximumPoolSize: .. " + SCHEDULED_POOL.getMaximumPoolSize();
stats[pos++] = " |- CompletedTaskCount: " + SCHEDULED_POOL.getCompletedTaskCount();
stats[pos++] = " |- QueuedTaskCount: .. " + SCHEDULED_POOL.getQueue().size();
stats[pos++] = " |- TaskCount: ........ " + SCHEDULED_POOL.getTaskCount();
stats[pos++] = " | -------";
stats[pos++] = "Instant pool:";
stats[pos++] = " |- ActiveCount: ...... " + INSTANT_POOL.getActiveCount();
stats[pos++] = " |- CorePoolSize: ..... " + INSTANT_POOL.getCorePoolSize();
stats[pos++] = " |- PoolSize: ......... " + INSTANT_POOL.getPoolSize();
stats[pos++] = " |- LargestPoolSize: .. " + INSTANT_POOL.getLargestPoolSize();
stats[pos++] = " |- MaximumPoolSize: .. " + INSTANT_POOL.getMaximumPoolSize();
stats[pos++] = " |- CompletedTaskCount: " + INSTANT_POOL.getCompletedTaskCount();
stats[pos++] = " |- QueuedTaskCount: .. " + INSTANT_POOL.getQueue().size();
stats[pos++] = " |- TaskCount: ........ " + INSTANT_POOL.getTaskCount();
stats[pos++] = " | -------";
return stats;
}
@ -198,14 +160,8 @@ public final class ThreadPool
try
{
LOGGER.info("ThreadPool: Shutting down.");
for (ScheduledThreadPoolExecutor threadPool : SCHEDULED_POOLS)
{
threadPool.shutdownNow();
}
for (ThreadPoolExecutor threadPool : INSTANT_POOLS)
{
threadPool.shutdownNow();
}
SCHEDULED_POOL.shutdownNow();
INSTANT_POOL.shutdownNow();
}
catch (Throwable t)
{

View File

@ -126,24 +126,16 @@ ServerListBrackets = False
# Thread Configuration
# ---------------------------------------------------------------------------
# Determines the amount of scheduled thread pools. If set to -1, the server will decide the amount depending on the available processors.
# Default: -1
ScheduledThreadPoolCount = -1
# Specifies how many threads will be in the scheduled pool.
# Default: 40
ScheduledThreadPoolCount = 40
# Specifies how many threads will be in a single scheduled pool.
# Default: 4
ThreadsPerScheduledThreadPool = 4
# Specifies how many threads will be in the single instant pool.
# Default: 20
InstantThreadPoolCount = 20
# Determines the amount of instant thread pools. If set to -1, the server will decide the amount depending on the available processors.
# Default: -1
InstantThreadPoolCount = -1
# Specifies how many threads will be in a single instant pool.
# Default: 2
ThreadsPerInstantThreadPool = 2
# Default: 2
UrgentPacketThreadCoreSize = 2
# Default: 20
UrgentPacketThreadCoreSize = 20
# Use threads to decrease startup time.
# Default: False

View File

@ -428,9 +428,7 @@ public final class Config
public static boolean ALT_DEV_SHOW_QUESTS_LOAD_IN_LOGS;
public static boolean ALT_DEV_SHOW_SCRIPTS_LOAD_IN_LOGS;
public static int SCHEDULED_THREAD_POOL_COUNT;
public static int THREADS_PER_SCHEDULED_THREAD_POOL;
public static int INSTANT_THREAD_POOL_COUNT;
public static int THREADS_PER_INSTANT_THREAD_POOL;
public static int IO_PACKET_THREAD_CORE_SIZE;
public static boolean THREADS_FOR_LOADING;
public static boolean DEADLOCK_DETECTOR;
@ -1354,19 +1352,9 @@ public final class Config
SERVER_LIST_AGE = serverSettings.getInt("ServerListAge", 0);
SERVER_LIST_BRACKET = serverSettings.getBoolean("ServerListBrackets", false);
SCHEDULED_THREAD_POOL_COUNT = serverSettings.getInt("ScheduledThreadPoolCount", -1);
if (SCHEDULED_THREAD_POOL_COUNT == -1)
{
SCHEDULED_THREAD_POOL_COUNT = Runtime.getRuntime().availableProcessors();
}
THREADS_PER_SCHEDULED_THREAD_POOL = serverSettings.getInt("ThreadsPerScheduledThreadPool", 4);
INSTANT_THREAD_POOL_COUNT = serverSettings.getInt("InstantThreadPoolCount", -1);
if (INSTANT_THREAD_POOL_COUNT == -1)
{
INSTANT_THREAD_POOL_COUNT = Runtime.getRuntime().availableProcessors();
}
THREADS_PER_INSTANT_THREAD_POOL = serverSettings.getInt("ThreadsPerInstantThreadPool", 2);
IO_PACKET_THREAD_CORE_SIZE = serverSettings.getInt("UrgentPacketThreadCoreSize", 2);
SCHEDULED_THREAD_POOL_COUNT = serverSettings.getInt("ScheduledThreadPoolCount", 40);
INSTANT_THREAD_POOL_COUNT = serverSettings.getInt("InstantThreadPoolCount", 20);
IO_PACKET_THREAD_CORE_SIZE = serverSettings.getInt("UrgentPacketThreadCoreSize", 20);
THREADS_FOR_LOADING = serverSettings.getBoolean("ThreadsForLoading", false);
DEADLOCK_DETECTOR = serverSettings.getBoolean("DeadLockDetector", true);

View File

@ -16,13 +16,17 @@
*/
package org.l2jmobius.commons.concurrent;
import java.lang.Thread.UncaughtExceptionHandler;
import java.util.logging.Logger;
import org.l2jmobius.Config;
/**
* @author UnAfraid
* @author Mobius
*/
public final class RunnableWrapper implements Runnable
{
private static final Logger LOGGER = Logger.getLogger(RunnableWrapper.class.getName());
private final Runnable _runnable;
public RunnableWrapper(Runnable runnable)
@ -37,14 +41,9 @@ public final class RunnableWrapper implements Runnable
{
_runnable.run();
}
catch (Throwable e)
catch (Exception e)
{
final Thread t = Thread.currentThread();
final UncaughtExceptionHandler h = t.getUncaughtExceptionHandler();
if (h != null)
{
h.uncaughtException(t, e);
}
LOGGER.warning(e.getMessage() + Config.EOL + e.getStackTrace());
}
}
}

View File

@ -26,10 +26,9 @@ import java.util.logging.Logger;
import org.l2jmobius.Config;
/**
* This class handles thread pooling system. It relies on two ThreadPoolExecutor arrays, which poolers number is generated using config.
* <p>
* Those arrays hold following pools:
* </p>
* This class handles thread pooling system.<br>
* It relies on two threadpool executors, which pool size is set using config.<br>
* Those arrays hold following pools:<br>
* <ul>
* <li>Scheduled pool keeps a track about incoming, future events.</li>
* <li>Instant pool handles short-life events.</li>
@ -39,59 +38,33 @@ public final class ThreadPool
{
private static final Logger LOGGER = Logger.getLogger(ThreadPool.class.getName());
private static ScheduledThreadPoolExecutor[] SCHEDULED_POOLS = new ScheduledThreadPoolExecutor[Config.SCHEDULED_THREAD_POOL_COUNT];
private static ThreadPoolExecutor[] INSTANT_POOLS = new ThreadPoolExecutor[Config.INSTANT_THREAD_POOL_COUNT];
private static volatile int SCHEDULED_THREAD_RANDOMIZER = 0;
private static volatile int INSTANT_THREAD_RANDOMIZER = 0;
private static final ScheduledThreadPoolExecutor SCHEDULED_POOL = new ScheduledThreadPoolExecutor(Config.SCHEDULED_THREAD_POOL_COUNT);
private static final ThreadPoolExecutor INSTANT_POOL = new ThreadPoolExecutor(Config.INSTANT_THREAD_POOL_COUNT, Config.INSTANT_THREAD_POOL_COUNT, 0, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(100000));
public static void init()
{
// Feed scheduled pool.
for (int i = 0; i < Config.SCHEDULED_THREAD_POOL_COUNT; i++)
{
SCHEDULED_POOLS[i] = new ScheduledThreadPoolExecutor(Config.THREADS_PER_SCHEDULED_THREAD_POOL);
}
// Feed instant pool.
for (int i = 0; i < Config.INSTANT_THREAD_POOL_COUNT; i++)
{
INSTANT_POOLS[i] = new ThreadPoolExecutor(Config.THREADS_PER_INSTANT_THREAD_POOL, Config.THREADS_PER_INSTANT_THREAD_POOL, 0, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(100000));
}
// Prestart core threads.
for (ScheduledThreadPoolExecutor threadPool : SCHEDULED_POOLS)
{
threadPool.setRejectedExecutionHandler(new RejectedExecutionHandlerImpl());
threadPool.setRemoveOnCancelPolicy(true);
threadPool.prestartAllCoreThreads();
}
for (ThreadPoolExecutor threadPool : INSTANT_POOLS)
{
threadPool.setRejectedExecutionHandler(new RejectedExecutionHandlerImpl());
threadPool.prestartAllCoreThreads();
}
// Set pool options.
SCHEDULED_POOL.setRejectedExecutionHandler(new RejectedExecutionHandlerImpl());
SCHEDULED_POOL.setRemoveOnCancelPolicy(true);
SCHEDULED_POOL.prestartAllCoreThreads();
INSTANT_POOL.setRejectedExecutionHandler(new RejectedExecutionHandlerImpl());
INSTANT_POOL.prestartAllCoreThreads();
// Launch purge task.
scheduleAtFixedRate(() ->
{
purge();
}, 600000, 600000);
}, 60000, 60000);
LOGGER.info("ThreadPool: Initialized");
LOGGER.info("..." + Config.SCHEDULED_THREAD_POOL_COUNT + " scheduled pool executors with " + (Config.SCHEDULED_THREAD_POOL_COUNT * Config.THREADS_PER_SCHEDULED_THREAD_POOL) + " total threads.");
LOGGER.info("..." + Config.INSTANT_THREAD_POOL_COUNT + " instant pool executors with " + (Config.INSTANT_THREAD_POOL_COUNT * Config.THREADS_PER_INSTANT_THREAD_POOL) + " total threads.");
LOGGER.info("...scheduled pool executor with " + Config.SCHEDULED_THREAD_POOL_COUNT + " total threads.");
LOGGER.info("...instant pool executor with " + Config.INSTANT_THREAD_POOL_COUNT + " total threads.");
}
public static void purge()
{
for (ScheduledThreadPoolExecutor threadPool : SCHEDULED_POOLS)
{
threadPool.purge();
}
for (ThreadPoolExecutor threadPool : INSTANT_POOLS)
{
threadPool.purge();
}
SCHEDULED_POOL.purge();
INSTANT_POOL.purge();
}
/**
@ -102,16 +75,14 @@ public final class ThreadPool
*/
public static ScheduledFuture<?> schedule(Runnable runnable, long delay)
{
synchronized (SCHEDULED_POOLS)
try
{
try
{
return SCHEDULED_POOLS[SCHEDULED_THREAD_RANDOMIZER++ % Config.SCHEDULED_THREAD_POOL_COUNT].schedule(new RunnableWrapper(runnable), delay, TimeUnit.MILLISECONDS);
}
catch (Exception e)
{
return null;
}
return SCHEDULED_POOL.schedule(new RunnableWrapper(runnable), delay, TimeUnit.MILLISECONDS);
}
catch (Exception e)
{
LOGGER.warning(e.getMessage() + Config.EOL + e.getStackTrace());
return null;
}
}
@ -124,16 +95,14 @@ public final class ThreadPool
*/
public static ScheduledFuture<?> scheduleAtFixedRate(Runnable runnable, long initialDelay, long period)
{
synchronized (SCHEDULED_POOLS)
try
{
try
{
return SCHEDULED_POOLS[SCHEDULED_THREAD_RANDOMIZER++ % Config.SCHEDULED_THREAD_POOL_COUNT].scheduleAtFixedRate(new RunnableWrapper(runnable), initialDelay, period, TimeUnit.MILLISECONDS);
}
catch (Exception e)
{
return null;
}
return SCHEDULED_POOL.scheduleAtFixedRate(new RunnableWrapper(runnable), initialDelay, period, TimeUnit.MILLISECONDS);
}
catch (Exception e)
{
LOGGER.warning(e.getMessage() + Config.EOL + e.getStackTrace());
return null;
}
}
@ -143,50 +112,43 @@ public final class ThreadPool
*/
public static void execute(Runnable runnable)
{
synchronized (INSTANT_POOLS)
try
{
try
{
INSTANT_POOLS[INSTANT_THREAD_RANDOMIZER++ % Config.INSTANT_THREAD_POOL_COUNT].execute(new RunnableWrapper(runnable));
}
catch (Exception e)
{
}
INSTANT_POOL.execute(new RunnableWrapper(runnable));
}
catch (Exception e)
{
LOGGER.warning(e.getMessage() + Config.EOL + e.getStackTrace());
}
}
public static String[] getStats()
{
final String[] stats = new String[(SCHEDULED_POOLS.length + INSTANT_POOLS.length) * 10];
final String[] stats = new String[20];
int pos = 0;
for (int i = 0; i < SCHEDULED_POOLS.length; i++)
{
final ScheduledThreadPoolExecutor threadPool = SCHEDULED_POOLS[i];
stats[pos++] = "Scheduled pool #" + i + ":";
stats[pos++] = " |- ActiveCount: ...... " + threadPool.getActiveCount();
stats[pos++] = " |- CorePoolSize: ..... " + threadPool.getCorePoolSize();
stats[pos++] = " |- PoolSize: ......... " + threadPool.getPoolSize();
stats[pos++] = " |- LargestPoolSize: .. " + threadPool.getLargestPoolSize();
stats[pos++] = " |- MaximumPoolSize: .. " + threadPool.getMaximumPoolSize();
stats[pos++] = " |- CompletedTaskCount: " + threadPool.getCompletedTaskCount();
stats[pos++] = " |- QueuedTaskCount: .. " + threadPool.getQueue().size();
stats[pos++] = " |- TaskCount: ........ " + threadPool.getTaskCount();
stats[pos++] = " | -------";
}
for (int i = 0; i < INSTANT_POOLS.length; i++)
{
final ThreadPoolExecutor threadPool = INSTANT_POOLS[i];
stats[pos++] = "Instant pool #" + i + ":";
stats[pos++] = " |- ActiveCount: ...... " + threadPool.getActiveCount();
stats[pos++] = " |- CorePoolSize: ..... " + threadPool.getCorePoolSize();
stats[pos++] = " |- PoolSize: ......... " + threadPool.getPoolSize();
stats[pos++] = " |- LargestPoolSize: .. " + threadPool.getLargestPoolSize();
stats[pos++] = " |- MaximumPoolSize: .. " + threadPool.getMaximumPoolSize();
stats[pos++] = " |- CompletedTaskCount: " + threadPool.getCompletedTaskCount();
stats[pos++] = " |- QueuedTaskCount: .. " + threadPool.getQueue().size();
stats[pos++] = " |- TaskCount: ........ " + threadPool.getTaskCount();
stats[pos++] = " | -------";
}
stats[pos++] = "Scheduled pool:";
stats[pos++] = " |- ActiveCount: ...... " + SCHEDULED_POOL.getActiveCount();
stats[pos++] = " |- CorePoolSize: ..... " + SCHEDULED_POOL.getCorePoolSize();
stats[pos++] = " |- PoolSize: ......... " + SCHEDULED_POOL.getPoolSize();
stats[pos++] = " |- LargestPoolSize: .. " + SCHEDULED_POOL.getLargestPoolSize();
stats[pos++] = " |- MaximumPoolSize: .. " + SCHEDULED_POOL.getMaximumPoolSize();
stats[pos++] = " |- CompletedTaskCount: " + SCHEDULED_POOL.getCompletedTaskCount();
stats[pos++] = " |- QueuedTaskCount: .. " + SCHEDULED_POOL.getQueue().size();
stats[pos++] = " |- TaskCount: ........ " + SCHEDULED_POOL.getTaskCount();
stats[pos++] = " | -------";
stats[pos++] = "Instant pool:";
stats[pos++] = " |- ActiveCount: ...... " + INSTANT_POOL.getActiveCount();
stats[pos++] = " |- CorePoolSize: ..... " + INSTANT_POOL.getCorePoolSize();
stats[pos++] = " |- PoolSize: ......... " + INSTANT_POOL.getPoolSize();
stats[pos++] = " |- LargestPoolSize: .. " + INSTANT_POOL.getLargestPoolSize();
stats[pos++] = " |- MaximumPoolSize: .. " + INSTANT_POOL.getMaximumPoolSize();
stats[pos++] = " |- CompletedTaskCount: " + INSTANT_POOL.getCompletedTaskCount();
stats[pos++] = " |- QueuedTaskCount: .. " + INSTANT_POOL.getQueue().size();
stats[pos++] = " |- TaskCount: ........ " + INSTANT_POOL.getTaskCount();
stats[pos++] = " | -------";
return stats;
}
@ -198,14 +160,8 @@ public final class ThreadPool
try
{
LOGGER.info("ThreadPool: Shutting down.");
for (ScheduledThreadPoolExecutor threadPool : SCHEDULED_POOLS)
{
threadPool.shutdownNow();
}
for (ThreadPoolExecutor threadPool : INSTANT_POOLS)
{
threadPool.shutdownNow();
}
SCHEDULED_POOL.shutdownNow();
INSTANT_POOL.shutdownNow();
}
catch (Throwable t)
{

View File

@ -126,24 +126,16 @@ ServerListBrackets = False
# Thread Configuration
# ---------------------------------------------------------------------------
# Determines the amount of scheduled thread pools. If set to -1, the server will decide the amount depending on the available processors.
# Default: -1
ScheduledThreadPoolCount = -1
# Specifies how many threads will be in the scheduled pool.
# Default: 40
ScheduledThreadPoolCount = 40
# Specifies how many threads will be in a single scheduled pool.
# Default: 4
ThreadsPerScheduledThreadPool = 4
# Specifies how many threads will be in the single instant pool.
# Default: 20
InstantThreadPoolCount = 20
# Determines the amount of instant thread pools. If set to -1, the server will decide the amount depending on the available processors.
# Default: -1
InstantThreadPoolCount = -1
# Specifies how many threads will be in a single instant pool.
# Default: 2
ThreadsPerInstantThreadPool = 2
# Default: 2
UrgentPacketThreadCoreSize = 2
# Default: 20
UrgentPacketThreadCoreSize = 20
# Use threads to decrease startup time.
# Default: False

View File

@ -424,9 +424,7 @@ public final class Config
public static boolean ALT_DEV_SHOW_QUESTS_LOAD_IN_LOGS;
public static boolean ALT_DEV_SHOW_SCRIPTS_LOAD_IN_LOGS;
public static int SCHEDULED_THREAD_POOL_COUNT;
public static int THREADS_PER_SCHEDULED_THREAD_POOL;
public static int INSTANT_THREAD_POOL_COUNT;
public static int THREADS_PER_INSTANT_THREAD_POOL;
public static int IO_PACKET_THREAD_CORE_SIZE;
public static boolean THREADS_FOR_LOADING;
public static boolean DEADLOCK_DETECTOR;
@ -1350,19 +1348,9 @@ public final class Config
SERVER_LIST_AGE = serverSettings.getInt("ServerListAge", 0);
SERVER_LIST_BRACKET = serverSettings.getBoolean("ServerListBrackets", false);
SCHEDULED_THREAD_POOL_COUNT = serverSettings.getInt("ScheduledThreadPoolCount", -1);
if (SCHEDULED_THREAD_POOL_COUNT == -1)
{
SCHEDULED_THREAD_POOL_COUNT = Runtime.getRuntime().availableProcessors();
}
THREADS_PER_SCHEDULED_THREAD_POOL = serverSettings.getInt("ThreadsPerScheduledThreadPool", 4);
INSTANT_THREAD_POOL_COUNT = serverSettings.getInt("InstantThreadPoolCount", -1);
if (INSTANT_THREAD_POOL_COUNT == -1)
{
INSTANT_THREAD_POOL_COUNT = Runtime.getRuntime().availableProcessors();
}
THREADS_PER_INSTANT_THREAD_POOL = serverSettings.getInt("ThreadsPerInstantThreadPool", 2);
IO_PACKET_THREAD_CORE_SIZE = serverSettings.getInt("UrgentPacketThreadCoreSize", 2);
SCHEDULED_THREAD_POOL_COUNT = serverSettings.getInt("ScheduledThreadPoolCount", 40);
INSTANT_THREAD_POOL_COUNT = serverSettings.getInt("InstantThreadPoolCount", 20);
IO_PACKET_THREAD_CORE_SIZE = serverSettings.getInt("UrgentPacketThreadCoreSize", 20);
THREADS_FOR_LOADING = serverSettings.getBoolean("ThreadsForLoading", false);
DEADLOCK_DETECTOR = serverSettings.getBoolean("DeadLockDetector", true);

View File

@ -16,13 +16,17 @@
*/
package org.l2jmobius.commons.concurrent;
import java.lang.Thread.UncaughtExceptionHandler;
import java.util.logging.Logger;
import org.l2jmobius.Config;
/**
* @author UnAfraid
* @author Mobius
*/
public final class RunnableWrapper implements Runnable
{
private static final Logger LOGGER = Logger.getLogger(RunnableWrapper.class.getName());
private final Runnable _runnable;
public RunnableWrapper(Runnable runnable)
@ -37,14 +41,9 @@ public final class RunnableWrapper implements Runnable
{
_runnable.run();
}
catch (Throwable e)
catch (Exception e)
{
final Thread t = Thread.currentThread();
final UncaughtExceptionHandler h = t.getUncaughtExceptionHandler();
if (h != null)
{
h.uncaughtException(t, e);
}
LOGGER.warning(e.getMessage() + Config.EOL + e.getStackTrace());
}
}
}

View File

@ -26,10 +26,9 @@ import java.util.logging.Logger;
import org.l2jmobius.Config;
/**
* This class handles thread pooling system. It relies on two ThreadPoolExecutor arrays, which poolers number is generated using config.
* <p>
* Those arrays hold following pools:
* </p>
* This class handles thread pooling system.<br>
* It relies on two threadpool executors, which pool size is set using config.<br>
* Those arrays hold following pools:<br>
* <ul>
* <li>Scheduled pool keeps a track about incoming, future events.</li>
* <li>Instant pool handles short-life events.</li>
@ -39,59 +38,33 @@ public final class ThreadPool
{
private static final Logger LOGGER = Logger.getLogger(ThreadPool.class.getName());
private static ScheduledThreadPoolExecutor[] SCHEDULED_POOLS = new ScheduledThreadPoolExecutor[Config.SCHEDULED_THREAD_POOL_COUNT];
private static ThreadPoolExecutor[] INSTANT_POOLS = new ThreadPoolExecutor[Config.INSTANT_THREAD_POOL_COUNT];
private static volatile int SCHEDULED_THREAD_RANDOMIZER = 0;
private static volatile int INSTANT_THREAD_RANDOMIZER = 0;
private static final ScheduledThreadPoolExecutor SCHEDULED_POOL = new ScheduledThreadPoolExecutor(Config.SCHEDULED_THREAD_POOL_COUNT);
private static final ThreadPoolExecutor INSTANT_POOL = new ThreadPoolExecutor(Config.INSTANT_THREAD_POOL_COUNT, Config.INSTANT_THREAD_POOL_COUNT, 0, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(100000));
public static void init()
{
// Feed scheduled pool.
for (int i = 0; i < Config.SCHEDULED_THREAD_POOL_COUNT; i++)
{
SCHEDULED_POOLS[i] = new ScheduledThreadPoolExecutor(Config.THREADS_PER_SCHEDULED_THREAD_POOL);
}
// Feed instant pool.
for (int i = 0; i < Config.INSTANT_THREAD_POOL_COUNT; i++)
{
INSTANT_POOLS[i] = new ThreadPoolExecutor(Config.THREADS_PER_INSTANT_THREAD_POOL, Config.THREADS_PER_INSTANT_THREAD_POOL, 0, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(100000));
}
// Prestart core threads.
for (ScheduledThreadPoolExecutor threadPool : SCHEDULED_POOLS)
{
threadPool.setRejectedExecutionHandler(new RejectedExecutionHandlerImpl());
threadPool.setRemoveOnCancelPolicy(true);
threadPool.prestartAllCoreThreads();
}
for (ThreadPoolExecutor threadPool : INSTANT_POOLS)
{
threadPool.setRejectedExecutionHandler(new RejectedExecutionHandlerImpl());
threadPool.prestartAllCoreThreads();
}
// Set pool options.
SCHEDULED_POOL.setRejectedExecutionHandler(new RejectedExecutionHandlerImpl());
SCHEDULED_POOL.setRemoveOnCancelPolicy(true);
SCHEDULED_POOL.prestartAllCoreThreads();
INSTANT_POOL.setRejectedExecutionHandler(new RejectedExecutionHandlerImpl());
INSTANT_POOL.prestartAllCoreThreads();
// Launch purge task.
scheduleAtFixedRate(() ->
{
purge();
}, 600000, 600000);
}, 60000, 60000);
LOGGER.info("ThreadPool: Initialized");
LOGGER.info("..." + Config.SCHEDULED_THREAD_POOL_COUNT + " scheduled pool executors with " + (Config.SCHEDULED_THREAD_POOL_COUNT * Config.THREADS_PER_SCHEDULED_THREAD_POOL) + " total threads.");
LOGGER.info("..." + Config.INSTANT_THREAD_POOL_COUNT + " instant pool executors with " + (Config.INSTANT_THREAD_POOL_COUNT * Config.THREADS_PER_INSTANT_THREAD_POOL) + " total threads.");
LOGGER.info("...scheduled pool executor with " + Config.SCHEDULED_THREAD_POOL_COUNT + " total threads.");
LOGGER.info("...instant pool executor with " + Config.INSTANT_THREAD_POOL_COUNT + " total threads.");
}
public static void purge()
{
for (ScheduledThreadPoolExecutor threadPool : SCHEDULED_POOLS)
{
threadPool.purge();
}
for (ThreadPoolExecutor threadPool : INSTANT_POOLS)
{
threadPool.purge();
}
SCHEDULED_POOL.purge();
INSTANT_POOL.purge();
}
/**
@ -102,16 +75,14 @@ public final class ThreadPool
*/
public static ScheduledFuture<?> schedule(Runnable runnable, long delay)
{
synchronized (SCHEDULED_POOLS)
try
{
try
{
return SCHEDULED_POOLS[SCHEDULED_THREAD_RANDOMIZER++ % Config.SCHEDULED_THREAD_POOL_COUNT].schedule(new RunnableWrapper(runnable), delay, TimeUnit.MILLISECONDS);
}
catch (Exception e)
{
return null;
}
return SCHEDULED_POOL.schedule(new RunnableWrapper(runnable), delay, TimeUnit.MILLISECONDS);
}
catch (Exception e)
{
LOGGER.warning(e.getMessage() + Config.EOL + e.getStackTrace());
return null;
}
}
@ -124,16 +95,14 @@ public final class ThreadPool
*/
public static ScheduledFuture<?> scheduleAtFixedRate(Runnable runnable, long initialDelay, long period)
{
synchronized (SCHEDULED_POOLS)
try
{
try
{
return SCHEDULED_POOLS[SCHEDULED_THREAD_RANDOMIZER++ % Config.SCHEDULED_THREAD_POOL_COUNT].scheduleAtFixedRate(new RunnableWrapper(runnable), initialDelay, period, TimeUnit.MILLISECONDS);
}
catch (Exception e)
{
return null;
}
return SCHEDULED_POOL.scheduleAtFixedRate(new RunnableWrapper(runnable), initialDelay, period, TimeUnit.MILLISECONDS);
}
catch (Exception e)
{
LOGGER.warning(e.getMessage() + Config.EOL + e.getStackTrace());
return null;
}
}
@ -143,50 +112,43 @@ public final class ThreadPool
*/
public static void execute(Runnable runnable)
{
synchronized (INSTANT_POOLS)
try
{
try
{
INSTANT_POOLS[INSTANT_THREAD_RANDOMIZER++ % Config.INSTANT_THREAD_POOL_COUNT].execute(new RunnableWrapper(runnable));
}
catch (Exception e)
{
}
INSTANT_POOL.execute(new RunnableWrapper(runnable));
}
catch (Exception e)
{
LOGGER.warning(e.getMessage() + Config.EOL + e.getStackTrace());
}
}
public static String[] getStats()
{
final String[] stats = new String[(SCHEDULED_POOLS.length + INSTANT_POOLS.length) * 10];
final String[] stats = new String[20];
int pos = 0;
for (int i = 0; i < SCHEDULED_POOLS.length; i++)
{
final ScheduledThreadPoolExecutor threadPool = SCHEDULED_POOLS[i];
stats[pos++] = "Scheduled pool #" + i + ":";
stats[pos++] = " |- ActiveCount: ...... " + threadPool.getActiveCount();
stats[pos++] = " |- CorePoolSize: ..... " + threadPool.getCorePoolSize();
stats[pos++] = " |- PoolSize: ......... " + threadPool.getPoolSize();
stats[pos++] = " |- LargestPoolSize: .. " + threadPool.getLargestPoolSize();
stats[pos++] = " |- MaximumPoolSize: .. " + threadPool.getMaximumPoolSize();
stats[pos++] = " |- CompletedTaskCount: " + threadPool.getCompletedTaskCount();
stats[pos++] = " |- QueuedTaskCount: .. " + threadPool.getQueue().size();
stats[pos++] = " |- TaskCount: ........ " + threadPool.getTaskCount();
stats[pos++] = " | -------";
}
for (int i = 0; i < INSTANT_POOLS.length; i++)
{
final ThreadPoolExecutor threadPool = INSTANT_POOLS[i];
stats[pos++] = "Instant pool #" + i + ":";
stats[pos++] = " |- ActiveCount: ...... " + threadPool.getActiveCount();
stats[pos++] = " |- CorePoolSize: ..... " + threadPool.getCorePoolSize();
stats[pos++] = " |- PoolSize: ......... " + threadPool.getPoolSize();
stats[pos++] = " |- LargestPoolSize: .. " + threadPool.getLargestPoolSize();
stats[pos++] = " |- MaximumPoolSize: .. " + threadPool.getMaximumPoolSize();
stats[pos++] = " |- CompletedTaskCount: " + threadPool.getCompletedTaskCount();
stats[pos++] = " |- QueuedTaskCount: .. " + threadPool.getQueue().size();
stats[pos++] = " |- TaskCount: ........ " + threadPool.getTaskCount();
stats[pos++] = " | -------";
}
stats[pos++] = "Scheduled pool:";
stats[pos++] = " |- ActiveCount: ...... " + SCHEDULED_POOL.getActiveCount();
stats[pos++] = " |- CorePoolSize: ..... " + SCHEDULED_POOL.getCorePoolSize();
stats[pos++] = " |- PoolSize: ......... " + SCHEDULED_POOL.getPoolSize();
stats[pos++] = " |- LargestPoolSize: .. " + SCHEDULED_POOL.getLargestPoolSize();
stats[pos++] = " |- MaximumPoolSize: .. " + SCHEDULED_POOL.getMaximumPoolSize();
stats[pos++] = " |- CompletedTaskCount: " + SCHEDULED_POOL.getCompletedTaskCount();
stats[pos++] = " |- QueuedTaskCount: .. " + SCHEDULED_POOL.getQueue().size();
stats[pos++] = " |- TaskCount: ........ " + SCHEDULED_POOL.getTaskCount();
stats[pos++] = " | -------";
stats[pos++] = "Instant pool:";
stats[pos++] = " |- ActiveCount: ...... " + INSTANT_POOL.getActiveCount();
stats[pos++] = " |- CorePoolSize: ..... " + INSTANT_POOL.getCorePoolSize();
stats[pos++] = " |- PoolSize: ......... " + INSTANT_POOL.getPoolSize();
stats[pos++] = " |- LargestPoolSize: .. " + INSTANT_POOL.getLargestPoolSize();
stats[pos++] = " |- MaximumPoolSize: .. " + INSTANT_POOL.getMaximumPoolSize();
stats[pos++] = " |- CompletedTaskCount: " + INSTANT_POOL.getCompletedTaskCount();
stats[pos++] = " |- QueuedTaskCount: .. " + INSTANT_POOL.getQueue().size();
stats[pos++] = " |- TaskCount: ........ " + INSTANT_POOL.getTaskCount();
stats[pos++] = " | -------";
return stats;
}
@ -198,14 +160,8 @@ public final class ThreadPool
try
{
LOGGER.info("ThreadPool: Shutting down.");
for (ScheduledThreadPoolExecutor threadPool : SCHEDULED_POOLS)
{
threadPool.shutdownNow();
}
for (ThreadPoolExecutor threadPool : INSTANT_POOLS)
{
threadPool.shutdownNow();
}
SCHEDULED_POOL.shutdownNow();
INSTANT_POOL.shutdownNow();
}
catch (Throwable t)
{

View File

@ -126,24 +126,16 @@ ServerListBrackets = False
# Thread Configuration
# ---------------------------------------------------------------------------
# Determines the amount of scheduled thread pools. If set to -1, the server will decide the amount depending on the available processors.
# Default: -1
ScheduledThreadPoolCount = -1
# Specifies how many threads will be in the scheduled pool.
# Default: 40
ScheduledThreadPoolCount = 40
# Specifies how many threads will be in a single scheduled pool.
# Default: 4
ThreadsPerScheduledThreadPool = 4
# Specifies how many threads will be in the single instant pool.
# Default: 20
InstantThreadPoolCount = 20
# Determines the amount of instant thread pools. If set to -1, the server will decide the amount depending on the available processors.
# Default: -1
InstantThreadPoolCount = -1
# Specifies how many threads will be in a single instant pool.
# Default: 2
ThreadsPerInstantThreadPool = 2
# Default: 2
UrgentPacketThreadCoreSize = 2
# Default: 20
UrgentPacketThreadCoreSize = 20
# Use threads to decrease startup time.
# Default: False

View File

@ -424,9 +424,7 @@ public final class Config
public static boolean ALT_DEV_SHOW_QUESTS_LOAD_IN_LOGS;
public static boolean ALT_DEV_SHOW_SCRIPTS_LOAD_IN_LOGS;
public static int SCHEDULED_THREAD_POOL_COUNT;
public static int THREADS_PER_SCHEDULED_THREAD_POOL;
public static int INSTANT_THREAD_POOL_COUNT;
public static int THREADS_PER_INSTANT_THREAD_POOL;
public static int IO_PACKET_THREAD_CORE_SIZE;
public static boolean THREADS_FOR_LOADING;
public static boolean DEADLOCK_DETECTOR;
@ -1350,19 +1348,9 @@ public final class Config
SERVER_LIST_AGE = serverSettings.getInt("ServerListAge", 0);
SERVER_LIST_BRACKET = serverSettings.getBoolean("ServerListBrackets", false);
SCHEDULED_THREAD_POOL_COUNT = serverSettings.getInt("ScheduledThreadPoolCount", -1);
if (SCHEDULED_THREAD_POOL_COUNT == -1)
{
SCHEDULED_THREAD_POOL_COUNT = Runtime.getRuntime().availableProcessors();
}
THREADS_PER_SCHEDULED_THREAD_POOL = serverSettings.getInt("ThreadsPerScheduledThreadPool", 4);
INSTANT_THREAD_POOL_COUNT = serverSettings.getInt("InstantThreadPoolCount", -1);
if (INSTANT_THREAD_POOL_COUNT == -1)
{
INSTANT_THREAD_POOL_COUNT = Runtime.getRuntime().availableProcessors();
}
THREADS_PER_INSTANT_THREAD_POOL = serverSettings.getInt("ThreadsPerInstantThreadPool", 2);
IO_PACKET_THREAD_CORE_SIZE = serverSettings.getInt("UrgentPacketThreadCoreSize", 2);
SCHEDULED_THREAD_POOL_COUNT = serverSettings.getInt("ScheduledThreadPoolCount", 40);
INSTANT_THREAD_POOL_COUNT = serverSettings.getInt("InstantThreadPoolCount", 20);
IO_PACKET_THREAD_CORE_SIZE = serverSettings.getInt("UrgentPacketThreadCoreSize", 20);
THREADS_FOR_LOADING = serverSettings.getBoolean("ThreadsForLoading", false);
DEADLOCK_DETECTOR = serverSettings.getBoolean("DeadLockDetector", true);

View File

@ -16,13 +16,17 @@
*/
package org.l2jmobius.commons.concurrent;
import java.lang.Thread.UncaughtExceptionHandler;
import java.util.logging.Logger;
import org.l2jmobius.Config;
/**
* @author UnAfraid
* @author Mobius
*/
public final class RunnableWrapper implements Runnable
{
private static final Logger LOGGER = Logger.getLogger(RunnableWrapper.class.getName());
private final Runnable _runnable;
public RunnableWrapper(Runnable runnable)
@ -37,14 +41,9 @@ public final class RunnableWrapper implements Runnable
{
_runnable.run();
}
catch (Throwable e)
catch (Exception e)
{
final Thread t = Thread.currentThread();
final UncaughtExceptionHandler h = t.getUncaughtExceptionHandler();
if (h != null)
{
h.uncaughtException(t, e);
}
LOGGER.warning(e.getMessage() + Config.EOL + e.getStackTrace());
}
}
}

View File

@ -26,10 +26,9 @@ import java.util.logging.Logger;
import org.l2jmobius.Config;
/**
* This class handles thread pooling system. It relies on two ThreadPoolExecutor arrays, which poolers number is generated using config.
* <p>
* Those arrays hold following pools:
* </p>
* This class handles thread pooling system.<br>
* It relies on two threadpool executors, which pool size is set using config.<br>
* Those arrays hold following pools:<br>
* <ul>
* <li>Scheduled pool keeps a track about incoming, future events.</li>
* <li>Instant pool handles short-life events.</li>
@ -39,59 +38,33 @@ public final class ThreadPool
{
private static final Logger LOGGER = Logger.getLogger(ThreadPool.class.getName());
private static ScheduledThreadPoolExecutor[] SCHEDULED_POOLS = new ScheduledThreadPoolExecutor[Config.SCHEDULED_THREAD_POOL_COUNT];
private static ThreadPoolExecutor[] INSTANT_POOLS = new ThreadPoolExecutor[Config.INSTANT_THREAD_POOL_COUNT];
private static volatile int SCHEDULED_THREAD_RANDOMIZER = 0;
private static volatile int INSTANT_THREAD_RANDOMIZER = 0;
private static final ScheduledThreadPoolExecutor SCHEDULED_POOL = new ScheduledThreadPoolExecutor(Config.SCHEDULED_THREAD_POOL_COUNT);
private static final ThreadPoolExecutor INSTANT_POOL = new ThreadPoolExecutor(Config.INSTANT_THREAD_POOL_COUNT, Config.INSTANT_THREAD_POOL_COUNT, 0, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(100000));
public static void init()
{
// Feed scheduled pool.
for (int i = 0; i < Config.SCHEDULED_THREAD_POOL_COUNT; i++)
{
SCHEDULED_POOLS[i] = new ScheduledThreadPoolExecutor(Config.THREADS_PER_SCHEDULED_THREAD_POOL);
}
// Feed instant pool.
for (int i = 0; i < Config.INSTANT_THREAD_POOL_COUNT; i++)
{
INSTANT_POOLS[i] = new ThreadPoolExecutor(Config.THREADS_PER_INSTANT_THREAD_POOL, Config.THREADS_PER_INSTANT_THREAD_POOL, 0, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(100000));
}
// Prestart core threads.
for (ScheduledThreadPoolExecutor threadPool : SCHEDULED_POOLS)
{
threadPool.setRejectedExecutionHandler(new RejectedExecutionHandlerImpl());
threadPool.setRemoveOnCancelPolicy(true);
threadPool.prestartAllCoreThreads();
}
for (ThreadPoolExecutor threadPool : INSTANT_POOLS)
{
threadPool.setRejectedExecutionHandler(new RejectedExecutionHandlerImpl());
threadPool.prestartAllCoreThreads();
}
// Set pool options.
SCHEDULED_POOL.setRejectedExecutionHandler(new RejectedExecutionHandlerImpl());
SCHEDULED_POOL.setRemoveOnCancelPolicy(true);
SCHEDULED_POOL.prestartAllCoreThreads();
INSTANT_POOL.setRejectedExecutionHandler(new RejectedExecutionHandlerImpl());
INSTANT_POOL.prestartAllCoreThreads();
// Launch purge task.
scheduleAtFixedRate(() ->
{
purge();
}, 600000, 600000);
}, 60000, 60000);
LOGGER.info("ThreadPool: Initialized");
LOGGER.info("..." + Config.SCHEDULED_THREAD_POOL_COUNT + " scheduled pool executors with " + (Config.SCHEDULED_THREAD_POOL_COUNT * Config.THREADS_PER_SCHEDULED_THREAD_POOL) + " total threads.");
LOGGER.info("..." + Config.INSTANT_THREAD_POOL_COUNT + " instant pool executors with " + (Config.INSTANT_THREAD_POOL_COUNT * Config.THREADS_PER_INSTANT_THREAD_POOL) + " total threads.");
LOGGER.info("...scheduled pool executor with " + Config.SCHEDULED_THREAD_POOL_COUNT + " total threads.");
LOGGER.info("...instant pool executor with " + Config.INSTANT_THREAD_POOL_COUNT + " total threads.");
}
public static void purge()
{
for (ScheduledThreadPoolExecutor threadPool : SCHEDULED_POOLS)
{
threadPool.purge();
}
for (ThreadPoolExecutor threadPool : INSTANT_POOLS)
{
threadPool.purge();
}
SCHEDULED_POOL.purge();
INSTANT_POOL.purge();
}
/**
@ -102,16 +75,14 @@ public final class ThreadPool
*/
public static ScheduledFuture<?> schedule(Runnable runnable, long delay)
{
synchronized (SCHEDULED_POOLS)
try
{
try
{
return SCHEDULED_POOLS[SCHEDULED_THREAD_RANDOMIZER++ % Config.SCHEDULED_THREAD_POOL_COUNT].schedule(new RunnableWrapper(runnable), delay, TimeUnit.MILLISECONDS);
}
catch (Exception e)
{
return null;
}
return SCHEDULED_POOL.schedule(new RunnableWrapper(runnable), delay, TimeUnit.MILLISECONDS);
}
catch (Exception e)
{
LOGGER.warning(e.getMessage() + Config.EOL + e.getStackTrace());
return null;
}
}
@ -124,16 +95,14 @@ public final class ThreadPool
*/
public static ScheduledFuture<?> scheduleAtFixedRate(Runnable runnable, long initialDelay, long period)
{
synchronized (SCHEDULED_POOLS)
try
{
try
{
return SCHEDULED_POOLS[SCHEDULED_THREAD_RANDOMIZER++ % Config.SCHEDULED_THREAD_POOL_COUNT].scheduleAtFixedRate(new RunnableWrapper(runnable), initialDelay, period, TimeUnit.MILLISECONDS);
}
catch (Exception e)
{
return null;
}
return SCHEDULED_POOL.scheduleAtFixedRate(new RunnableWrapper(runnable), initialDelay, period, TimeUnit.MILLISECONDS);
}
catch (Exception e)
{
LOGGER.warning(e.getMessage() + Config.EOL + e.getStackTrace());
return null;
}
}
@ -143,50 +112,43 @@ public final class ThreadPool
*/
public static void execute(Runnable runnable)
{
synchronized (INSTANT_POOLS)
try
{
try
{
INSTANT_POOLS[INSTANT_THREAD_RANDOMIZER++ % Config.INSTANT_THREAD_POOL_COUNT].execute(new RunnableWrapper(runnable));
}
catch (Exception e)
{
}
INSTANT_POOL.execute(new RunnableWrapper(runnable));
}
catch (Exception e)
{
LOGGER.warning(e.getMessage() + Config.EOL + e.getStackTrace());
}
}
public static String[] getStats()
{
final String[] stats = new String[(SCHEDULED_POOLS.length + INSTANT_POOLS.length) * 10];
final String[] stats = new String[20];
int pos = 0;
for (int i = 0; i < SCHEDULED_POOLS.length; i++)
{
final ScheduledThreadPoolExecutor threadPool = SCHEDULED_POOLS[i];
stats[pos++] = "Scheduled pool #" + i + ":";
stats[pos++] = " |- ActiveCount: ...... " + threadPool.getActiveCount();
stats[pos++] = " |- CorePoolSize: ..... " + threadPool.getCorePoolSize();
stats[pos++] = " |- PoolSize: ......... " + threadPool.getPoolSize();
stats[pos++] = " |- LargestPoolSize: .. " + threadPool.getLargestPoolSize();
stats[pos++] = " |- MaximumPoolSize: .. " + threadPool.getMaximumPoolSize();
stats[pos++] = " |- CompletedTaskCount: " + threadPool.getCompletedTaskCount();
stats[pos++] = " |- QueuedTaskCount: .. " + threadPool.getQueue().size();
stats[pos++] = " |- TaskCount: ........ " + threadPool.getTaskCount();
stats[pos++] = " | -------";
}
for (int i = 0; i < INSTANT_POOLS.length; i++)
{
final ThreadPoolExecutor threadPool = INSTANT_POOLS[i];
stats[pos++] = "Instant pool #" + i + ":";
stats[pos++] = " |- ActiveCount: ...... " + threadPool.getActiveCount();
stats[pos++] = " |- CorePoolSize: ..... " + threadPool.getCorePoolSize();
stats[pos++] = " |- PoolSize: ......... " + threadPool.getPoolSize();
stats[pos++] = " |- LargestPoolSize: .. " + threadPool.getLargestPoolSize();
stats[pos++] = " |- MaximumPoolSize: .. " + threadPool.getMaximumPoolSize();
stats[pos++] = " |- CompletedTaskCount: " + threadPool.getCompletedTaskCount();
stats[pos++] = " |- QueuedTaskCount: .. " + threadPool.getQueue().size();
stats[pos++] = " |- TaskCount: ........ " + threadPool.getTaskCount();
stats[pos++] = " | -------";
}
stats[pos++] = "Scheduled pool:";
stats[pos++] = " |- ActiveCount: ...... " + SCHEDULED_POOL.getActiveCount();
stats[pos++] = " |- CorePoolSize: ..... " + SCHEDULED_POOL.getCorePoolSize();
stats[pos++] = " |- PoolSize: ......... " + SCHEDULED_POOL.getPoolSize();
stats[pos++] = " |- LargestPoolSize: .. " + SCHEDULED_POOL.getLargestPoolSize();
stats[pos++] = " |- MaximumPoolSize: .. " + SCHEDULED_POOL.getMaximumPoolSize();
stats[pos++] = " |- CompletedTaskCount: " + SCHEDULED_POOL.getCompletedTaskCount();
stats[pos++] = " |- QueuedTaskCount: .. " + SCHEDULED_POOL.getQueue().size();
stats[pos++] = " |- TaskCount: ........ " + SCHEDULED_POOL.getTaskCount();
stats[pos++] = " | -------";
stats[pos++] = "Instant pool:";
stats[pos++] = " |- ActiveCount: ...... " + INSTANT_POOL.getActiveCount();
stats[pos++] = " |- CorePoolSize: ..... " + INSTANT_POOL.getCorePoolSize();
stats[pos++] = " |- PoolSize: ......... " + INSTANT_POOL.getPoolSize();
stats[pos++] = " |- LargestPoolSize: .. " + INSTANT_POOL.getLargestPoolSize();
stats[pos++] = " |- MaximumPoolSize: .. " + INSTANT_POOL.getMaximumPoolSize();
stats[pos++] = " |- CompletedTaskCount: " + INSTANT_POOL.getCompletedTaskCount();
stats[pos++] = " |- QueuedTaskCount: .. " + INSTANT_POOL.getQueue().size();
stats[pos++] = " |- TaskCount: ........ " + INSTANT_POOL.getTaskCount();
stats[pos++] = " | -------";
return stats;
}
@ -198,14 +160,8 @@ public final class ThreadPool
try
{
LOGGER.info("ThreadPool: Shutting down.");
for (ScheduledThreadPoolExecutor threadPool : SCHEDULED_POOLS)
{
threadPool.shutdownNow();
}
for (ThreadPoolExecutor threadPool : INSTANT_POOLS)
{
threadPool.shutdownNow();
}
SCHEDULED_POOL.shutdownNow();
INSTANT_POOL.shutdownNow();
}
catch (Throwable t)
{

View File

@ -126,24 +126,16 @@ ServerListBrackets = False
# Thread Configuration
# ---------------------------------------------------------------------------
# Determines the amount of scheduled thread pools. If set to -1, the server will decide the amount depending on the available processors.
# Default: -1
ScheduledThreadPoolCount = -1
# Specifies how many threads will be in the scheduled pool.
# Default: 40
ScheduledThreadPoolCount = 40
# Specifies how many threads will be in a single scheduled pool.
# Default: 4
ThreadsPerScheduledThreadPool = 4
# Specifies how many threads will be in the single instant pool.
# Default: 20
InstantThreadPoolCount = 20
# Determines the amount of instant thread pools. If set to -1, the server will decide the amount depending on the available processors.
# Default: -1
InstantThreadPoolCount = -1
# Specifies how many threads will be in a single instant pool.
# Default: 2
ThreadsPerInstantThreadPool = 2
# Default: 2
UrgentPacketThreadCoreSize = 2
# Default: 20
UrgentPacketThreadCoreSize = 20
# Use threads to decrease startup time.
# Default: False

View File

@ -425,9 +425,7 @@ public final class Config
public static boolean ALT_DEV_SHOW_QUESTS_LOAD_IN_LOGS;
public static boolean ALT_DEV_SHOW_SCRIPTS_LOAD_IN_LOGS;
public static int SCHEDULED_THREAD_POOL_COUNT;
public static int THREADS_PER_SCHEDULED_THREAD_POOL;
public static int INSTANT_THREAD_POOL_COUNT;
public static int THREADS_PER_INSTANT_THREAD_POOL;
public static int IO_PACKET_THREAD_CORE_SIZE;
public static boolean THREADS_FOR_LOADING;
public static boolean DEADLOCK_DETECTOR;
@ -1367,19 +1365,9 @@ public final class Config
SERVER_LIST_AGE = serverSettings.getInt("ServerListAge", 0);
SERVER_LIST_BRACKET = serverSettings.getBoolean("ServerListBrackets", false);
SCHEDULED_THREAD_POOL_COUNT = serverSettings.getInt("ScheduledThreadPoolCount", -1);
if (SCHEDULED_THREAD_POOL_COUNT == -1)
{
SCHEDULED_THREAD_POOL_COUNT = Runtime.getRuntime().availableProcessors();
}
THREADS_PER_SCHEDULED_THREAD_POOL = serverSettings.getInt("ThreadsPerScheduledThreadPool", 4);
INSTANT_THREAD_POOL_COUNT = serverSettings.getInt("InstantThreadPoolCount", -1);
if (INSTANT_THREAD_POOL_COUNT == -1)
{
INSTANT_THREAD_POOL_COUNT = Runtime.getRuntime().availableProcessors();
}
THREADS_PER_INSTANT_THREAD_POOL = serverSettings.getInt("ThreadsPerInstantThreadPool", 2);
IO_PACKET_THREAD_CORE_SIZE = serverSettings.getInt("UrgentPacketThreadCoreSize", 2);
SCHEDULED_THREAD_POOL_COUNT = serverSettings.getInt("ScheduledThreadPoolCount", 40);
INSTANT_THREAD_POOL_COUNT = serverSettings.getInt("InstantThreadPoolCount", 20);
IO_PACKET_THREAD_CORE_SIZE = serverSettings.getInt("UrgentPacketThreadCoreSize", 20);
THREADS_FOR_LOADING = serverSettings.getBoolean("ThreadsForLoading", false);
DEADLOCK_DETECTOR = serverSettings.getBoolean("DeadLockDetector", true);

View File

@ -16,13 +16,17 @@
*/
package org.l2jmobius.commons.concurrent;
import java.lang.Thread.UncaughtExceptionHandler;
import java.util.logging.Logger;
import org.l2jmobius.Config;
/**
* @author UnAfraid
* @author Mobius
*/
public final class RunnableWrapper implements Runnable
{
private static final Logger LOGGER = Logger.getLogger(RunnableWrapper.class.getName());
private final Runnable _runnable;
public RunnableWrapper(Runnable runnable)
@ -37,14 +41,9 @@ public final class RunnableWrapper implements Runnable
{
_runnable.run();
}
catch (Throwable e)
catch (Exception e)
{
final Thread t = Thread.currentThread();
final UncaughtExceptionHandler h = t.getUncaughtExceptionHandler();
if (h != null)
{
h.uncaughtException(t, e);
}
LOGGER.warning(e.getMessage() + Config.EOL + e.getStackTrace());
}
}
}

View File

@ -26,10 +26,9 @@ import java.util.logging.Logger;
import org.l2jmobius.Config;
/**
* This class handles thread pooling system. It relies on two ThreadPoolExecutor arrays, which poolers number is generated using config.
* <p>
* Those arrays hold following pools:
* </p>
* This class handles thread pooling system.<br>
* It relies on two threadpool executors, which pool size is set using config.<br>
* Those arrays hold following pools:<br>
* <ul>
* <li>Scheduled pool keeps a track about incoming, future events.</li>
* <li>Instant pool handles short-life events.</li>
@ -39,59 +38,33 @@ public final class ThreadPool
{
private static final Logger LOGGER = Logger.getLogger(ThreadPool.class.getName());
private static ScheduledThreadPoolExecutor[] SCHEDULED_POOLS = new ScheduledThreadPoolExecutor[Config.SCHEDULED_THREAD_POOL_COUNT];
private static ThreadPoolExecutor[] INSTANT_POOLS = new ThreadPoolExecutor[Config.INSTANT_THREAD_POOL_COUNT];
private static volatile int SCHEDULED_THREAD_RANDOMIZER = 0;
private static volatile int INSTANT_THREAD_RANDOMIZER = 0;
private static final ScheduledThreadPoolExecutor SCHEDULED_POOL = new ScheduledThreadPoolExecutor(Config.SCHEDULED_THREAD_POOL_COUNT);
private static final ThreadPoolExecutor INSTANT_POOL = new ThreadPoolExecutor(Config.INSTANT_THREAD_POOL_COUNT, Config.INSTANT_THREAD_POOL_COUNT, 0, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(100000));
public static void init()
{
// Feed scheduled pool.
for (int i = 0; i < Config.SCHEDULED_THREAD_POOL_COUNT; i++)
{
SCHEDULED_POOLS[i] = new ScheduledThreadPoolExecutor(Config.THREADS_PER_SCHEDULED_THREAD_POOL);
}
// Feed instant pool.
for (int i = 0; i < Config.INSTANT_THREAD_POOL_COUNT; i++)
{
INSTANT_POOLS[i] = new ThreadPoolExecutor(Config.THREADS_PER_INSTANT_THREAD_POOL, Config.THREADS_PER_INSTANT_THREAD_POOL, 0, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(100000));
}
// Prestart core threads.
for (ScheduledThreadPoolExecutor threadPool : SCHEDULED_POOLS)
{
threadPool.setRejectedExecutionHandler(new RejectedExecutionHandlerImpl());
threadPool.setRemoveOnCancelPolicy(true);
threadPool.prestartAllCoreThreads();
}
for (ThreadPoolExecutor threadPool : INSTANT_POOLS)
{
threadPool.setRejectedExecutionHandler(new RejectedExecutionHandlerImpl());
threadPool.prestartAllCoreThreads();
}
// Set pool options.
SCHEDULED_POOL.setRejectedExecutionHandler(new RejectedExecutionHandlerImpl());
SCHEDULED_POOL.setRemoveOnCancelPolicy(true);
SCHEDULED_POOL.prestartAllCoreThreads();
INSTANT_POOL.setRejectedExecutionHandler(new RejectedExecutionHandlerImpl());
INSTANT_POOL.prestartAllCoreThreads();
// Launch purge task.
scheduleAtFixedRate(() ->
{
purge();
}, 600000, 600000);
}, 60000, 60000);
LOGGER.info("ThreadPool: Initialized");
LOGGER.info("..." + Config.SCHEDULED_THREAD_POOL_COUNT + " scheduled pool executors with " + (Config.SCHEDULED_THREAD_POOL_COUNT * Config.THREADS_PER_SCHEDULED_THREAD_POOL) + " total threads.");
LOGGER.info("..." + Config.INSTANT_THREAD_POOL_COUNT + " instant pool executors with " + (Config.INSTANT_THREAD_POOL_COUNT * Config.THREADS_PER_INSTANT_THREAD_POOL) + " total threads.");
LOGGER.info("...scheduled pool executor with " + Config.SCHEDULED_THREAD_POOL_COUNT + " total threads.");
LOGGER.info("...instant pool executor with " + Config.INSTANT_THREAD_POOL_COUNT + " total threads.");
}
public static void purge()
{
for (ScheduledThreadPoolExecutor threadPool : SCHEDULED_POOLS)
{
threadPool.purge();
}
for (ThreadPoolExecutor threadPool : INSTANT_POOLS)
{
threadPool.purge();
}
SCHEDULED_POOL.purge();
INSTANT_POOL.purge();
}
/**
@ -102,16 +75,14 @@ public final class ThreadPool
*/
public static ScheduledFuture<?> schedule(Runnable runnable, long delay)
{
synchronized (SCHEDULED_POOLS)
try
{
try
{
return SCHEDULED_POOLS[SCHEDULED_THREAD_RANDOMIZER++ % Config.SCHEDULED_THREAD_POOL_COUNT].schedule(new RunnableWrapper(runnable), delay, TimeUnit.MILLISECONDS);
}
catch (Exception e)
{
return null;
}
return SCHEDULED_POOL.schedule(new RunnableWrapper(runnable), delay, TimeUnit.MILLISECONDS);
}
catch (Exception e)
{
LOGGER.warning(e.getMessage() + Config.EOL + e.getStackTrace());
return null;
}
}
@ -124,16 +95,14 @@ public final class ThreadPool
*/
public static ScheduledFuture<?> scheduleAtFixedRate(Runnable runnable, long initialDelay, long period)
{
synchronized (SCHEDULED_POOLS)
try
{
try
{
return SCHEDULED_POOLS[SCHEDULED_THREAD_RANDOMIZER++ % Config.SCHEDULED_THREAD_POOL_COUNT].scheduleAtFixedRate(new RunnableWrapper(runnable), initialDelay, period, TimeUnit.MILLISECONDS);
}
catch (Exception e)
{
return null;
}
return SCHEDULED_POOL.scheduleAtFixedRate(new RunnableWrapper(runnable), initialDelay, period, TimeUnit.MILLISECONDS);
}
catch (Exception e)
{
LOGGER.warning(e.getMessage() + Config.EOL + e.getStackTrace());
return null;
}
}
@ -143,50 +112,43 @@ public final class ThreadPool
*/
public static void execute(Runnable runnable)
{
synchronized (INSTANT_POOLS)
try
{
try
{
INSTANT_POOLS[INSTANT_THREAD_RANDOMIZER++ % Config.INSTANT_THREAD_POOL_COUNT].execute(new RunnableWrapper(runnable));
}
catch (Exception e)
{
}
INSTANT_POOL.execute(new RunnableWrapper(runnable));
}
catch (Exception e)
{
LOGGER.warning(e.getMessage() + Config.EOL + e.getStackTrace());
}
}
public static String[] getStats()
{
final String[] stats = new String[(SCHEDULED_POOLS.length + INSTANT_POOLS.length) * 10];
final String[] stats = new String[20];
int pos = 0;
for (int i = 0; i < SCHEDULED_POOLS.length; i++)
{
final ScheduledThreadPoolExecutor threadPool = SCHEDULED_POOLS[i];
stats[pos++] = "Scheduled pool #" + i + ":";
stats[pos++] = " |- ActiveCount: ...... " + threadPool.getActiveCount();
stats[pos++] = " |- CorePoolSize: ..... " + threadPool.getCorePoolSize();
stats[pos++] = " |- PoolSize: ......... " + threadPool.getPoolSize();
stats[pos++] = " |- LargestPoolSize: .. " + threadPool.getLargestPoolSize();
stats[pos++] = " |- MaximumPoolSize: .. " + threadPool.getMaximumPoolSize();
stats[pos++] = " |- CompletedTaskCount: " + threadPool.getCompletedTaskCount();
stats[pos++] = " |- QueuedTaskCount: .. " + threadPool.getQueue().size();
stats[pos++] = " |- TaskCount: ........ " + threadPool.getTaskCount();
stats[pos++] = " | -------";
}
for (int i = 0; i < INSTANT_POOLS.length; i++)
{
final ThreadPoolExecutor threadPool = INSTANT_POOLS[i];
stats[pos++] = "Instant pool #" + i + ":";
stats[pos++] = " |- ActiveCount: ...... " + threadPool.getActiveCount();
stats[pos++] = " |- CorePoolSize: ..... " + threadPool.getCorePoolSize();
stats[pos++] = " |- PoolSize: ......... " + threadPool.getPoolSize();
stats[pos++] = " |- LargestPoolSize: .. " + threadPool.getLargestPoolSize();
stats[pos++] = " |- MaximumPoolSize: .. " + threadPool.getMaximumPoolSize();
stats[pos++] = " |- CompletedTaskCount: " + threadPool.getCompletedTaskCount();
stats[pos++] = " |- QueuedTaskCount: .. " + threadPool.getQueue().size();
stats[pos++] = " |- TaskCount: ........ " + threadPool.getTaskCount();
stats[pos++] = " | -------";
}
stats[pos++] = "Scheduled pool:";
stats[pos++] = " |- ActiveCount: ...... " + SCHEDULED_POOL.getActiveCount();
stats[pos++] = " |- CorePoolSize: ..... " + SCHEDULED_POOL.getCorePoolSize();
stats[pos++] = " |- PoolSize: ......... " + SCHEDULED_POOL.getPoolSize();
stats[pos++] = " |- LargestPoolSize: .. " + SCHEDULED_POOL.getLargestPoolSize();
stats[pos++] = " |- MaximumPoolSize: .. " + SCHEDULED_POOL.getMaximumPoolSize();
stats[pos++] = " |- CompletedTaskCount: " + SCHEDULED_POOL.getCompletedTaskCount();
stats[pos++] = " |- QueuedTaskCount: .. " + SCHEDULED_POOL.getQueue().size();
stats[pos++] = " |- TaskCount: ........ " + SCHEDULED_POOL.getTaskCount();
stats[pos++] = " | -------";
stats[pos++] = "Instant pool:";
stats[pos++] = " |- ActiveCount: ...... " + INSTANT_POOL.getActiveCount();
stats[pos++] = " |- CorePoolSize: ..... " + INSTANT_POOL.getCorePoolSize();
stats[pos++] = " |- PoolSize: ......... " + INSTANT_POOL.getPoolSize();
stats[pos++] = " |- LargestPoolSize: .. " + INSTANT_POOL.getLargestPoolSize();
stats[pos++] = " |- MaximumPoolSize: .. " + INSTANT_POOL.getMaximumPoolSize();
stats[pos++] = " |- CompletedTaskCount: " + INSTANT_POOL.getCompletedTaskCount();
stats[pos++] = " |- QueuedTaskCount: .. " + INSTANT_POOL.getQueue().size();
stats[pos++] = " |- TaskCount: ........ " + INSTANT_POOL.getTaskCount();
stats[pos++] = " | -------";
return stats;
}
@ -198,14 +160,8 @@ public final class ThreadPool
try
{
LOGGER.info("ThreadPool: Shutting down.");
for (ScheduledThreadPoolExecutor threadPool : SCHEDULED_POOLS)
{
threadPool.shutdownNow();
}
for (ThreadPoolExecutor threadPool : INSTANT_POOLS)
{
threadPool.shutdownNow();
}
SCHEDULED_POOL.shutdownNow();
INSTANT_POOL.shutdownNow();
}
catch (Throwable t)
{

View File

@ -83,22 +83,13 @@ LogItems = False
# ---------------------------------------------------------------------------
# Thread Configuration
# ---------------------------------------------------------------------------
# Specifies how many threads will be in the scheduled pool.
# Default: 40
ScheduledThreadPoolCount = 40
# Determines the amount of scheduled thread pools. If set to -1, the server will decide the amount depending on the available processors.
# Default: -1
ScheduledThreadPoolCount = -1
# Specifies how many threads will be in a single scheduled pool.
# Default: 4
ThreadsPerScheduledThreadPool = 4
# Determines the amount of instant thread pools. If set to -1, the server will decide the amount depending on the available processors.
# Default: -1
InstantThreadPoolCount = -1
# Specifies how many threads will be in a single instant pool.
# Default: 2
ThreadsPerInstantThreadPool = 2
# Specifies how many threads will be in the single instant pool.
# Default: 20
InstantThreadPoolCount = 20
# This is the server id that the gameserver will request (i.e. 1 is Bartz)
RequestServerID = 1

View File

@ -661,9 +661,7 @@ public final class Config
public static boolean LOG_ITEMS;
public static int SCHEDULED_THREAD_POOL_COUNT;
public static int THREADS_PER_SCHEDULED_THREAD_POOL;
public static int INSTANT_THREAD_POOL_COUNT;
public static int THREADS_PER_INSTANT_THREAD_POOL;
public static boolean LAZY_CACHE;
@ -2327,18 +2325,8 @@ public final class Config
LOG_CHAT = Boolean.valueOf(devSettings.getProperty("LogChat", "false"));
LOG_ITEMS = Boolean.valueOf(devSettings.getProperty("LogItems", "false"));
SCHEDULED_THREAD_POOL_COUNT = Integer.parseInt(devSettings.getProperty("ScheduledThreadPoolCount", "-1"));
if (SCHEDULED_THREAD_POOL_COUNT == -1)
{
SCHEDULED_THREAD_POOL_COUNT = Runtime.getRuntime().availableProcessors();
}
THREADS_PER_SCHEDULED_THREAD_POOL = Integer.parseInt(devSettings.getProperty("ThreadsPerScheduledThreadPool", "4"));
INSTANT_THREAD_POOL_COUNT = Integer.parseInt(devSettings.getProperty("InstantThreadPoolCount", "-1"));
if (INSTANT_THREAD_POOL_COUNT == -1)
{
INSTANT_THREAD_POOL_COUNT = Runtime.getRuntime().availableProcessors();
}
THREADS_PER_INSTANT_THREAD_POOL = Integer.parseInt(devSettings.getProperty("ThreadsPerInstantThreadPool", "2"));
SCHEDULED_THREAD_POOL_COUNT = Integer.parseInt(devSettings.getProperty("ScheduledThreadPoolCount", "40"));
INSTANT_THREAD_POOL_COUNT = Integer.parseInt(devSettings.getProperty("InstantThreadPoolCount", "20"));
LAZY_CACHE = Boolean.valueOf(devSettings.getProperty("LazyCache", "false"));
}

View File

@ -16,13 +16,17 @@
*/
package org.l2jmobius.commons.concurrent;
import java.lang.Thread.UncaughtExceptionHandler;
import java.util.logging.Logger;
import org.l2jmobius.Config;
/**
* @author UnAfraid
* @author Mobius
*/
public final class RunnableWrapper implements Runnable
{
private static final Logger LOGGER = Logger.getLogger(RunnableWrapper.class.getName());
private final Runnable _runnable;
public RunnableWrapper(Runnable runnable)
@ -37,14 +41,9 @@ public final class RunnableWrapper implements Runnable
{
_runnable.run();
}
catch (Throwable e)
catch (Exception e)
{
final Thread t = Thread.currentThread();
final UncaughtExceptionHandler h = t.getUncaughtExceptionHandler();
if (h != null)
{
h.uncaughtException(t, e);
}
LOGGER.warning(e.getMessage() + Config.EOL + e.getStackTrace());
}
}
}

View File

@ -26,10 +26,9 @@ import java.util.logging.Logger;
import org.l2jmobius.Config;
/**
* This class handles thread pooling system. It relies on two ThreadPoolExecutor arrays, which poolers number is generated using config.
* <p>
* Those arrays hold following pools:
* </p>
* This class handles thread pooling system.<br>
* It relies on two threadpool executors, which pool size is set using config.<br>
* Those arrays hold following pools:<br>
* <ul>
* <li>Scheduled pool keeps a track about incoming, future events.</li>
* <li>Instant pool handles short-life events.</li>
@ -39,59 +38,33 @@ public final class ThreadPool
{
private static final Logger LOGGER = Logger.getLogger(ThreadPool.class.getName());
private static ScheduledThreadPoolExecutor[] SCHEDULED_POOLS = new ScheduledThreadPoolExecutor[Config.SCHEDULED_THREAD_POOL_COUNT];
private static ThreadPoolExecutor[] INSTANT_POOLS = new ThreadPoolExecutor[Config.INSTANT_THREAD_POOL_COUNT];
private static volatile int SCHEDULED_THREAD_RANDOMIZER = 0;
private static volatile int INSTANT_THREAD_RANDOMIZER = 0;
private static final ScheduledThreadPoolExecutor SCHEDULED_POOL = new ScheduledThreadPoolExecutor(Config.SCHEDULED_THREAD_POOL_COUNT);
private static final ThreadPoolExecutor INSTANT_POOL = new ThreadPoolExecutor(Config.INSTANT_THREAD_POOL_COUNT, Config.INSTANT_THREAD_POOL_COUNT, 0, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(100000));
public static void init()
{
// Feed scheduled pool.
for (int i = 0; i < Config.SCHEDULED_THREAD_POOL_COUNT; i++)
{
SCHEDULED_POOLS[i] = new ScheduledThreadPoolExecutor(Config.THREADS_PER_SCHEDULED_THREAD_POOL);
}
// Feed instant pool.
for (int i = 0; i < Config.INSTANT_THREAD_POOL_COUNT; i++)
{
INSTANT_POOLS[i] = new ThreadPoolExecutor(Config.THREADS_PER_INSTANT_THREAD_POOL, Config.THREADS_PER_INSTANT_THREAD_POOL, 0, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(100000));
}
// Prestart core threads.
for (ScheduledThreadPoolExecutor threadPool : SCHEDULED_POOLS)
{
threadPool.setRejectedExecutionHandler(new RejectedExecutionHandlerImpl());
threadPool.setRemoveOnCancelPolicy(true);
threadPool.prestartAllCoreThreads();
}
for (ThreadPoolExecutor threadPool : INSTANT_POOLS)
{
threadPool.setRejectedExecutionHandler(new RejectedExecutionHandlerImpl());
threadPool.prestartAllCoreThreads();
}
// Set pool options.
SCHEDULED_POOL.setRejectedExecutionHandler(new RejectedExecutionHandlerImpl());
SCHEDULED_POOL.setRemoveOnCancelPolicy(true);
SCHEDULED_POOL.prestartAllCoreThreads();
INSTANT_POOL.setRejectedExecutionHandler(new RejectedExecutionHandlerImpl());
INSTANT_POOL.prestartAllCoreThreads();
// Launch purge task.
scheduleAtFixedRate(() ->
{
purge();
}, 600000, 600000);
}, 60000, 60000);
LOGGER.info("ThreadPool: Initialized");
LOGGER.info("..." + Config.SCHEDULED_THREAD_POOL_COUNT + " scheduled pool executors with " + (Config.SCHEDULED_THREAD_POOL_COUNT * Config.THREADS_PER_SCHEDULED_THREAD_POOL) + " total threads.");
LOGGER.info("..." + Config.INSTANT_THREAD_POOL_COUNT + " instant pool executors with " + (Config.INSTANT_THREAD_POOL_COUNT * Config.THREADS_PER_INSTANT_THREAD_POOL) + " total threads.");
LOGGER.info("...scheduled pool executor with " + Config.SCHEDULED_THREAD_POOL_COUNT + " total threads.");
LOGGER.info("...instant pool executor with " + Config.INSTANT_THREAD_POOL_COUNT + " total threads.");
}
public static void purge()
{
for (ScheduledThreadPoolExecutor threadPool : SCHEDULED_POOLS)
{
threadPool.purge();
}
for (ThreadPoolExecutor threadPool : INSTANT_POOLS)
{
threadPool.purge();
}
SCHEDULED_POOL.purge();
INSTANT_POOL.purge();
}
/**
@ -102,16 +75,14 @@ public final class ThreadPool
*/
public static ScheduledFuture<?> schedule(Runnable runnable, long delay)
{
synchronized (SCHEDULED_POOLS)
try
{
try
{
return SCHEDULED_POOLS[SCHEDULED_THREAD_RANDOMIZER++ % Config.SCHEDULED_THREAD_POOL_COUNT].schedule(new RunnableWrapper(runnable), delay, TimeUnit.MILLISECONDS);
}
catch (Exception e)
{
return null;
}
return SCHEDULED_POOL.schedule(new RunnableWrapper(runnable), delay, TimeUnit.MILLISECONDS);
}
catch (Exception e)
{
LOGGER.warning(e.getMessage() + Config.EOL + e.getStackTrace());
return null;
}
}
@ -124,16 +95,14 @@ public final class ThreadPool
*/
public static ScheduledFuture<?> scheduleAtFixedRate(Runnable runnable, long initialDelay, long period)
{
synchronized (SCHEDULED_POOLS)
try
{
try
{
return SCHEDULED_POOLS[SCHEDULED_THREAD_RANDOMIZER++ % Config.SCHEDULED_THREAD_POOL_COUNT].scheduleAtFixedRate(new RunnableWrapper(runnable), initialDelay, period, TimeUnit.MILLISECONDS);
}
catch (Exception e)
{
return null;
}
return SCHEDULED_POOL.scheduleAtFixedRate(new RunnableWrapper(runnable), initialDelay, period, TimeUnit.MILLISECONDS);
}
catch (Exception e)
{
LOGGER.warning(e.getMessage() + Config.EOL + e.getStackTrace());
return null;
}
}
@ -143,50 +112,43 @@ public final class ThreadPool
*/
public static void execute(Runnable runnable)
{
synchronized (INSTANT_POOLS)
try
{
try
{
INSTANT_POOLS[INSTANT_THREAD_RANDOMIZER++ % Config.INSTANT_THREAD_POOL_COUNT].execute(new RunnableWrapper(runnable));
}
catch (Exception e)
{
}
INSTANT_POOL.execute(new RunnableWrapper(runnable));
}
catch (Exception e)
{
LOGGER.warning(e.getMessage() + Config.EOL + e.getStackTrace());
}
}
public static String[] getStats()
{
final String[] stats = new String[(SCHEDULED_POOLS.length + INSTANT_POOLS.length) * 10];
final String[] stats = new String[20];
int pos = 0;
for (int i = 0; i < SCHEDULED_POOLS.length; i++)
{
final ScheduledThreadPoolExecutor threadPool = SCHEDULED_POOLS[i];
stats[pos++] = "Scheduled pool #" + i + ":";
stats[pos++] = " |- ActiveCount: ...... " + threadPool.getActiveCount();
stats[pos++] = " |- CorePoolSize: ..... " + threadPool.getCorePoolSize();
stats[pos++] = " |- PoolSize: ......... " + threadPool.getPoolSize();
stats[pos++] = " |- LargestPoolSize: .. " + threadPool.getLargestPoolSize();
stats[pos++] = " |- MaximumPoolSize: .. " + threadPool.getMaximumPoolSize();
stats[pos++] = " |- CompletedTaskCount: " + threadPool.getCompletedTaskCount();
stats[pos++] = " |- QueuedTaskCount: .. " + threadPool.getQueue().size();
stats[pos++] = " |- TaskCount: ........ " + threadPool.getTaskCount();
stats[pos++] = " | -------";
}
for (int i = 0; i < INSTANT_POOLS.length; i++)
{
final ThreadPoolExecutor threadPool = INSTANT_POOLS[i];
stats[pos++] = "Instant pool #" + i + ":";
stats[pos++] = " |- ActiveCount: ...... " + threadPool.getActiveCount();
stats[pos++] = " |- CorePoolSize: ..... " + threadPool.getCorePoolSize();
stats[pos++] = " |- PoolSize: ......... " + threadPool.getPoolSize();
stats[pos++] = " |- LargestPoolSize: .. " + threadPool.getLargestPoolSize();
stats[pos++] = " |- MaximumPoolSize: .. " + threadPool.getMaximumPoolSize();
stats[pos++] = " |- CompletedTaskCount: " + threadPool.getCompletedTaskCount();
stats[pos++] = " |- QueuedTaskCount: .. " + threadPool.getQueue().size();
stats[pos++] = " |- TaskCount: ........ " + threadPool.getTaskCount();
stats[pos++] = " | -------";
}
stats[pos++] = "Scheduled pool:";
stats[pos++] = " |- ActiveCount: ...... " + SCHEDULED_POOL.getActiveCount();
stats[pos++] = " |- CorePoolSize: ..... " + SCHEDULED_POOL.getCorePoolSize();
stats[pos++] = " |- PoolSize: ......... " + SCHEDULED_POOL.getPoolSize();
stats[pos++] = " |- LargestPoolSize: .. " + SCHEDULED_POOL.getLargestPoolSize();
stats[pos++] = " |- MaximumPoolSize: .. " + SCHEDULED_POOL.getMaximumPoolSize();
stats[pos++] = " |- CompletedTaskCount: " + SCHEDULED_POOL.getCompletedTaskCount();
stats[pos++] = " |- QueuedTaskCount: .. " + SCHEDULED_POOL.getQueue().size();
stats[pos++] = " |- TaskCount: ........ " + SCHEDULED_POOL.getTaskCount();
stats[pos++] = " | -------";
stats[pos++] = "Instant pool:";
stats[pos++] = " |- ActiveCount: ...... " + INSTANT_POOL.getActiveCount();
stats[pos++] = " |- CorePoolSize: ..... " + INSTANT_POOL.getCorePoolSize();
stats[pos++] = " |- PoolSize: ......... " + INSTANT_POOL.getPoolSize();
stats[pos++] = " |- LargestPoolSize: .. " + INSTANT_POOL.getLargestPoolSize();
stats[pos++] = " |- MaximumPoolSize: .. " + INSTANT_POOL.getMaximumPoolSize();
stats[pos++] = " |- CompletedTaskCount: " + INSTANT_POOL.getCompletedTaskCount();
stats[pos++] = " |- QueuedTaskCount: .. " + INSTANT_POOL.getQueue().size();
stats[pos++] = " |- TaskCount: ........ " + INSTANT_POOL.getTaskCount();
stats[pos++] = " | -------";
return stats;
}
@ -198,14 +160,8 @@ public final class ThreadPool
try
{
LOGGER.info("ThreadPool: Shutting down.");
for (ScheduledThreadPoolExecutor threadPool : SCHEDULED_POOLS)
{
threadPool.shutdownNow();
}
for (ThreadPoolExecutor threadPool : INSTANT_POOLS)
{
threadPool.shutdownNow();
}
SCHEDULED_POOL.shutdownNow();
INSTANT_POOL.shutdownNow();
}
catch (Throwable t)
{

View File

@ -126,24 +126,16 @@ ServerListBrackets = False
# Thread Configuration
# ---------------------------------------------------------------------------
# Determines the amount of scheduled thread pools. If set to -1, the server will decide the amount depending on the available processors.
# Default: -1
ScheduledThreadPoolCount = -1
# Specifies how many threads will be in the scheduled pool.
# Default: 40
ScheduledThreadPoolCount = 40
# Specifies how many threads will be in a single scheduled pool.
# Default: 4
ThreadsPerScheduledThreadPool = 4
# Specifies how many threads will be in the single instant pool.
# Default: 20
InstantThreadPoolCount = 20
# Determines the amount of instant thread pools. If set to -1, the server will decide the amount depending on the available processors.
# Default: -1
InstantThreadPoolCount = -1
# Specifies how many threads will be in a single instant pool.
# Default: 2
ThreadsPerInstantThreadPool = 2
# Default: 2
UrgentPacketThreadCoreSize = 2
# Default: 20
UrgentPacketThreadCoreSize = 20
# Use threads to decrease startup time.
# Default: False

View File

@ -501,9 +501,7 @@ public final class Config
public static boolean ALT_DEV_SHOW_QUESTS_LOAD_IN_LOGS;
public static boolean ALT_DEV_SHOW_SCRIPTS_LOAD_IN_LOGS;
public static int SCHEDULED_THREAD_POOL_COUNT;
public static int THREADS_PER_SCHEDULED_THREAD_POOL;
public static int INSTANT_THREAD_POOL_COUNT;
public static int THREADS_PER_INSTANT_THREAD_POOL;
public static int IO_PACKET_THREAD_CORE_SIZE;
public static boolean THREADS_FOR_LOADING;
public static boolean DEADLOCK_DETECTOR;
@ -1452,19 +1450,9 @@ public final class Config
SERVER_LIST_AGE = serverSettings.getInt("ServerListAge", 0);
SERVER_LIST_BRACKET = serverSettings.getBoolean("ServerListBrackets", false);
SCHEDULED_THREAD_POOL_COUNT = serverSettings.getInt("ScheduledThreadPoolCount", -1);
if (SCHEDULED_THREAD_POOL_COUNT == -1)
{
SCHEDULED_THREAD_POOL_COUNT = Runtime.getRuntime().availableProcessors();
}
THREADS_PER_SCHEDULED_THREAD_POOL = serverSettings.getInt("ThreadsPerScheduledThreadPool", 4);
INSTANT_THREAD_POOL_COUNT = serverSettings.getInt("InstantThreadPoolCount", -1);
if (INSTANT_THREAD_POOL_COUNT == -1)
{
INSTANT_THREAD_POOL_COUNT = Runtime.getRuntime().availableProcessors();
}
THREADS_PER_INSTANT_THREAD_POOL = serverSettings.getInt("ThreadsPerInstantThreadPool", 2);
IO_PACKET_THREAD_CORE_SIZE = serverSettings.getInt("UrgentPacketThreadCoreSize", 2);
SCHEDULED_THREAD_POOL_COUNT = serverSettings.getInt("ScheduledThreadPoolCount", 40);
INSTANT_THREAD_POOL_COUNT = serverSettings.getInt("InstantThreadPoolCount", 20);
IO_PACKET_THREAD_CORE_SIZE = serverSettings.getInt("UrgentPacketThreadCoreSize", 20);
THREADS_FOR_LOADING = serverSettings.getBoolean("ThreadsForLoading", false);
DEADLOCK_DETECTOR = serverSettings.getBoolean("DeadLockDetector", true);

View File

@ -16,13 +16,17 @@
*/
package org.l2jmobius.commons.concurrent;
import java.lang.Thread.UncaughtExceptionHandler;
import java.util.logging.Logger;
import org.l2jmobius.Config;
/**
* @author UnAfraid
* @author Mobius
*/
public final class RunnableWrapper implements Runnable
{
private static final Logger LOGGER = Logger.getLogger(RunnableWrapper.class.getName());
private final Runnable _runnable;
public RunnableWrapper(Runnable runnable)
@ -37,14 +41,9 @@ public final class RunnableWrapper implements Runnable
{
_runnable.run();
}
catch (Throwable e)
catch (Exception e)
{
final Thread t = Thread.currentThread();
final UncaughtExceptionHandler h = t.getUncaughtExceptionHandler();
if (h != null)
{
h.uncaughtException(t, e);
}
LOGGER.warning(e.getMessage() + Config.EOL + e.getStackTrace());
}
}
}

View File

@ -26,10 +26,9 @@ import java.util.logging.Logger;
import org.l2jmobius.Config;
/**
* This class handles thread pooling system. It relies on two ThreadPoolExecutor arrays, which poolers number is generated using config.
* <p>
* Those arrays hold following pools:
* </p>
* This class handles thread pooling system.<br>
* It relies on two threadpool executors, which pool size is set using config.<br>
* Those arrays hold following pools:<br>
* <ul>
* <li>Scheduled pool keeps a track about incoming, future events.</li>
* <li>Instant pool handles short-life events.</li>
@ -39,59 +38,33 @@ public final class ThreadPool
{
private static final Logger LOGGER = Logger.getLogger(ThreadPool.class.getName());
private static ScheduledThreadPoolExecutor[] SCHEDULED_POOLS = new ScheduledThreadPoolExecutor[Config.SCHEDULED_THREAD_POOL_COUNT];
private static ThreadPoolExecutor[] INSTANT_POOLS = new ThreadPoolExecutor[Config.INSTANT_THREAD_POOL_COUNT];
private static volatile int SCHEDULED_THREAD_RANDOMIZER = 0;
private static volatile int INSTANT_THREAD_RANDOMIZER = 0;
private static final ScheduledThreadPoolExecutor SCHEDULED_POOL = new ScheduledThreadPoolExecutor(Config.SCHEDULED_THREAD_POOL_COUNT);
private static final ThreadPoolExecutor INSTANT_POOL = new ThreadPoolExecutor(Config.INSTANT_THREAD_POOL_COUNT, Config.INSTANT_THREAD_POOL_COUNT, 0, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(100000));
public static void init()
{
// Feed scheduled pool.
for (int i = 0; i < Config.SCHEDULED_THREAD_POOL_COUNT; i++)
{
SCHEDULED_POOLS[i] = new ScheduledThreadPoolExecutor(Config.THREADS_PER_SCHEDULED_THREAD_POOL);
}
// Feed instant pool.
for (int i = 0; i < Config.INSTANT_THREAD_POOL_COUNT; i++)
{
INSTANT_POOLS[i] = new ThreadPoolExecutor(Config.THREADS_PER_INSTANT_THREAD_POOL, Config.THREADS_PER_INSTANT_THREAD_POOL, 0, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(100000));
}
// Prestart core threads.
for (ScheduledThreadPoolExecutor threadPool : SCHEDULED_POOLS)
{
threadPool.setRejectedExecutionHandler(new RejectedExecutionHandlerImpl());
threadPool.setRemoveOnCancelPolicy(true);
threadPool.prestartAllCoreThreads();
}
for (ThreadPoolExecutor threadPool : INSTANT_POOLS)
{
threadPool.setRejectedExecutionHandler(new RejectedExecutionHandlerImpl());
threadPool.prestartAllCoreThreads();
}
// Set pool options.
SCHEDULED_POOL.setRejectedExecutionHandler(new RejectedExecutionHandlerImpl());
SCHEDULED_POOL.setRemoveOnCancelPolicy(true);
SCHEDULED_POOL.prestartAllCoreThreads();
INSTANT_POOL.setRejectedExecutionHandler(new RejectedExecutionHandlerImpl());
INSTANT_POOL.prestartAllCoreThreads();
// Launch purge task.
scheduleAtFixedRate(() ->
{
purge();
}, 600000, 600000);
}, 60000, 60000);
LOGGER.info("ThreadPool: Initialized");
LOGGER.info("..." + Config.SCHEDULED_THREAD_POOL_COUNT + " scheduled pool executors with " + (Config.SCHEDULED_THREAD_POOL_COUNT * Config.THREADS_PER_SCHEDULED_THREAD_POOL) + " total threads.");
LOGGER.info("..." + Config.INSTANT_THREAD_POOL_COUNT + " instant pool executors with " + (Config.INSTANT_THREAD_POOL_COUNT * Config.THREADS_PER_INSTANT_THREAD_POOL) + " total threads.");
LOGGER.info("...scheduled pool executor with " + Config.SCHEDULED_THREAD_POOL_COUNT + " total threads.");
LOGGER.info("...instant pool executor with " + Config.INSTANT_THREAD_POOL_COUNT + " total threads.");
}
public static void purge()
{
for (ScheduledThreadPoolExecutor threadPool : SCHEDULED_POOLS)
{
threadPool.purge();
}
for (ThreadPoolExecutor threadPool : INSTANT_POOLS)
{
threadPool.purge();
}
SCHEDULED_POOL.purge();
INSTANT_POOL.purge();
}
/**
@ -102,16 +75,14 @@ public final class ThreadPool
*/
public static ScheduledFuture<?> schedule(Runnable runnable, long delay)
{
synchronized (SCHEDULED_POOLS)
try
{
try
{
return SCHEDULED_POOLS[SCHEDULED_THREAD_RANDOMIZER++ % Config.SCHEDULED_THREAD_POOL_COUNT].schedule(new RunnableWrapper(runnable), delay, TimeUnit.MILLISECONDS);
}
catch (Exception e)
{
return null;
}
return SCHEDULED_POOL.schedule(new RunnableWrapper(runnable), delay, TimeUnit.MILLISECONDS);
}
catch (Exception e)
{
LOGGER.warning(e.getMessage() + Config.EOL + e.getStackTrace());
return null;
}
}
@ -124,16 +95,14 @@ public final class ThreadPool
*/
public static ScheduledFuture<?> scheduleAtFixedRate(Runnable runnable, long initialDelay, long period)
{
synchronized (SCHEDULED_POOLS)
try
{
try
{
return SCHEDULED_POOLS[SCHEDULED_THREAD_RANDOMIZER++ % Config.SCHEDULED_THREAD_POOL_COUNT].scheduleAtFixedRate(new RunnableWrapper(runnable), initialDelay, period, TimeUnit.MILLISECONDS);
}
catch (Exception e)
{
return null;
}
return SCHEDULED_POOL.scheduleAtFixedRate(new RunnableWrapper(runnable), initialDelay, period, TimeUnit.MILLISECONDS);
}
catch (Exception e)
{
LOGGER.warning(e.getMessage() + Config.EOL + e.getStackTrace());
return null;
}
}
@ -143,50 +112,43 @@ public final class ThreadPool
*/
public static void execute(Runnable runnable)
{
synchronized (INSTANT_POOLS)
try
{
try
{
INSTANT_POOLS[INSTANT_THREAD_RANDOMIZER++ % Config.INSTANT_THREAD_POOL_COUNT].execute(new RunnableWrapper(runnable));
}
catch (Exception e)
{
}
INSTANT_POOL.execute(new RunnableWrapper(runnable));
}
catch (Exception e)
{
LOGGER.warning(e.getMessage() + Config.EOL + e.getStackTrace());
}
}
public static String[] getStats()
{
final String[] stats = new String[(SCHEDULED_POOLS.length + INSTANT_POOLS.length) * 10];
final String[] stats = new String[20];
int pos = 0;
for (int i = 0; i < SCHEDULED_POOLS.length; i++)
{
final ScheduledThreadPoolExecutor threadPool = SCHEDULED_POOLS[i];
stats[pos++] = "Scheduled pool #" + i + ":";
stats[pos++] = " |- ActiveCount: ...... " + threadPool.getActiveCount();
stats[pos++] = " |- CorePoolSize: ..... " + threadPool.getCorePoolSize();
stats[pos++] = " |- PoolSize: ......... " + threadPool.getPoolSize();
stats[pos++] = " |- LargestPoolSize: .. " + threadPool.getLargestPoolSize();
stats[pos++] = " |- MaximumPoolSize: .. " + threadPool.getMaximumPoolSize();
stats[pos++] = " |- CompletedTaskCount: " + threadPool.getCompletedTaskCount();
stats[pos++] = " |- QueuedTaskCount: .. " + threadPool.getQueue().size();
stats[pos++] = " |- TaskCount: ........ " + threadPool.getTaskCount();
stats[pos++] = " | -------";
}
for (int i = 0; i < INSTANT_POOLS.length; i++)
{
final ThreadPoolExecutor threadPool = INSTANT_POOLS[i];
stats[pos++] = "Instant pool #" + i + ":";
stats[pos++] = " |- ActiveCount: ...... " + threadPool.getActiveCount();
stats[pos++] = " |- CorePoolSize: ..... " + threadPool.getCorePoolSize();
stats[pos++] = " |- PoolSize: ......... " + threadPool.getPoolSize();
stats[pos++] = " |- LargestPoolSize: .. " + threadPool.getLargestPoolSize();
stats[pos++] = " |- MaximumPoolSize: .. " + threadPool.getMaximumPoolSize();
stats[pos++] = " |- CompletedTaskCount: " + threadPool.getCompletedTaskCount();
stats[pos++] = " |- QueuedTaskCount: .. " + threadPool.getQueue().size();
stats[pos++] = " |- TaskCount: ........ " + threadPool.getTaskCount();
stats[pos++] = " | -------";
}
stats[pos++] = "Scheduled pool:";
stats[pos++] = " |- ActiveCount: ...... " + SCHEDULED_POOL.getActiveCount();
stats[pos++] = " |- CorePoolSize: ..... " + SCHEDULED_POOL.getCorePoolSize();
stats[pos++] = " |- PoolSize: ......... " + SCHEDULED_POOL.getPoolSize();
stats[pos++] = " |- LargestPoolSize: .. " + SCHEDULED_POOL.getLargestPoolSize();
stats[pos++] = " |- MaximumPoolSize: .. " + SCHEDULED_POOL.getMaximumPoolSize();
stats[pos++] = " |- CompletedTaskCount: " + SCHEDULED_POOL.getCompletedTaskCount();
stats[pos++] = " |- QueuedTaskCount: .. " + SCHEDULED_POOL.getQueue().size();
stats[pos++] = " |- TaskCount: ........ " + SCHEDULED_POOL.getTaskCount();
stats[pos++] = " | -------";
stats[pos++] = "Instant pool:";
stats[pos++] = " |- ActiveCount: ...... " + INSTANT_POOL.getActiveCount();
stats[pos++] = " |- CorePoolSize: ..... " + INSTANT_POOL.getCorePoolSize();
stats[pos++] = " |- PoolSize: ......... " + INSTANT_POOL.getPoolSize();
stats[pos++] = " |- LargestPoolSize: .. " + INSTANT_POOL.getLargestPoolSize();
stats[pos++] = " |- MaximumPoolSize: .. " + INSTANT_POOL.getMaximumPoolSize();
stats[pos++] = " |- CompletedTaskCount: " + INSTANT_POOL.getCompletedTaskCount();
stats[pos++] = " |- QueuedTaskCount: .. " + INSTANT_POOL.getQueue().size();
stats[pos++] = " |- TaskCount: ........ " + INSTANT_POOL.getTaskCount();
stats[pos++] = " | -------";
return stats;
}
@ -198,14 +160,8 @@ public final class ThreadPool
try
{
LOGGER.info("ThreadPool: Shutting down.");
for (ScheduledThreadPoolExecutor threadPool : SCHEDULED_POOLS)
{
threadPool.shutdownNow();
}
for (ThreadPoolExecutor threadPool : INSTANT_POOLS)
{
threadPool.shutdownNow();
}
SCHEDULED_POOL.shutdownNow();
INSTANT_POOL.shutdownNow();
}
catch (Throwable t)
{

View File

@ -126,24 +126,16 @@ ServerListBrackets = False
# Thread Configuration
# ---------------------------------------------------------------------------
# Determines the amount of scheduled thread pools. If set to -1, the server will decide the amount depending on the available processors.
# Default: -1
ScheduledThreadPoolCount = -1
# Specifies how many threads will be in the scheduled pool.
# Default: 40
ScheduledThreadPoolCount = 40
# Specifies how many threads will be in a single scheduled pool.
# Default: 4
ThreadsPerScheduledThreadPool = 4
# Specifies how many threads will be in the single instant pool.
# Default: 20
InstantThreadPoolCount = 20
# Determines the amount of instant thread pools. If set to -1, the server will decide the amount depending on the available processors.
# Default: -1
InstantThreadPoolCount = -1
# Specifies how many threads will be in a single instant pool.
# Default: 2
ThreadsPerInstantThreadPool = 2
# Default: 2
UrgentPacketThreadCoreSize = 2
# Default: 20
UrgentPacketThreadCoreSize = 20
# Use threads to decrease startup time.
# Default: False

View File

@ -434,9 +434,7 @@ public final class Config
public static boolean ALT_DEV_SHOW_QUESTS_LOAD_IN_LOGS;
public static boolean ALT_DEV_SHOW_SCRIPTS_LOAD_IN_LOGS;
public static int SCHEDULED_THREAD_POOL_COUNT;
public static int THREADS_PER_SCHEDULED_THREAD_POOL;
public static int INSTANT_THREAD_POOL_COUNT;
public static int THREADS_PER_INSTANT_THREAD_POOL;
public static int IO_PACKET_THREAD_CORE_SIZE;
public static boolean THREADS_FOR_LOADING;
public static boolean DEADLOCK_DETECTOR;
@ -1293,19 +1291,9 @@ public final class Config
SERVER_LIST_AGE = serverSettings.getInt("ServerListAge", 0);
SERVER_LIST_BRACKET = serverSettings.getBoolean("ServerListBrackets", false);
SCHEDULED_THREAD_POOL_COUNT = serverSettings.getInt("ScheduledThreadPoolCount", -1);
if (SCHEDULED_THREAD_POOL_COUNT == -1)
{
SCHEDULED_THREAD_POOL_COUNT = Runtime.getRuntime().availableProcessors();
}
THREADS_PER_SCHEDULED_THREAD_POOL = serverSettings.getInt("ThreadsPerScheduledThreadPool", 4);
INSTANT_THREAD_POOL_COUNT = serverSettings.getInt("InstantThreadPoolCount", -1);
if (INSTANT_THREAD_POOL_COUNT == -1)
{
INSTANT_THREAD_POOL_COUNT = Runtime.getRuntime().availableProcessors();
}
THREADS_PER_INSTANT_THREAD_POOL = serverSettings.getInt("ThreadsPerInstantThreadPool", 2);
IO_PACKET_THREAD_CORE_SIZE = serverSettings.getInt("UrgentPacketThreadCoreSize", 2);
SCHEDULED_THREAD_POOL_COUNT = serverSettings.getInt("ScheduledThreadPoolCount", 40);
INSTANT_THREAD_POOL_COUNT = serverSettings.getInt("InstantThreadPoolCount", 20);
IO_PACKET_THREAD_CORE_SIZE = serverSettings.getInt("UrgentPacketThreadCoreSize", 20);
THREADS_FOR_LOADING = serverSettings.getBoolean("ThreadsForLoading", false);
DEADLOCK_DETECTOR = serverSettings.getBoolean("DeadLockDetector", true);

View File

@ -16,13 +16,17 @@
*/
package org.l2jmobius.commons.concurrent;
import java.lang.Thread.UncaughtExceptionHandler;
import java.util.logging.Logger;
import org.l2jmobius.Config;
/**
* @author UnAfraid
* @author Mobius
*/
public final class RunnableWrapper implements Runnable
{
private static final Logger LOGGER = Logger.getLogger(RunnableWrapper.class.getName());
private final Runnable _runnable;
public RunnableWrapper(Runnable runnable)
@ -37,14 +41,9 @@ public final class RunnableWrapper implements Runnable
{
_runnable.run();
}
catch (Throwable e)
catch (Exception e)
{
final Thread t = Thread.currentThread();
final UncaughtExceptionHandler h = t.getUncaughtExceptionHandler();
if (h != null)
{
h.uncaughtException(t, e);
}
LOGGER.warning(e.getMessage() + Config.EOL + e.getStackTrace());
}
}
}

View File

@ -26,10 +26,9 @@ import java.util.logging.Logger;
import org.l2jmobius.Config;
/**
* This class handles thread pooling system. It relies on two ThreadPoolExecutor arrays, which poolers number is generated using config.
* <p>
* Those arrays hold following pools:
* </p>
* This class handles thread pooling system.<br>
* It relies on two threadpool executors, which pool size is set using config.<br>
* Those arrays hold following pools:<br>
* <ul>
* <li>Scheduled pool keeps a track about incoming, future events.</li>
* <li>Instant pool handles short-life events.</li>
@ -39,59 +38,33 @@ public final class ThreadPool
{
private static final Logger LOGGER = Logger.getLogger(ThreadPool.class.getName());
private static ScheduledThreadPoolExecutor[] SCHEDULED_POOLS = new ScheduledThreadPoolExecutor[Config.SCHEDULED_THREAD_POOL_COUNT];
private static ThreadPoolExecutor[] INSTANT_POOLS = new ThreadPoolExecutor[Config.INSTANT_THREAD_POOL_COUNT];
private static volatile int SCHEDULED_THREAD_RANDOMIZER = 0;
private static volatile int INSTANT_THREAD_RANDOMIZER = 0;
private static final ScheduledThreadPoolExecutor SCHEDULED_POOL = new ScheduledThreadPoolExecutor(Config.SCHEDULED_THREAD_POOL_COUNT);
private static final ThreadPoolExecutor INSTANT_POOL = new ThreadPoolExecutor(Config.INSTANT_THREAD_POOL_COUNT, Config.INSTANT_THREAD_POOL_COUNT, 0, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(100000));
public static void init()
{
// Feed scheduled pool.
for (int i = 0; i < Config.SCHEDULED_THREAD_POOL_COUNT; i++)
{
SCHEDULED_POOLS[i] = new ScheduledThreadPoolExecutor(Config.THREADS_PER_SCHEDULED_THREAD_POOL);
}
// Feed instant pool.
for (int i = 0; i < Config.INSTANT_THREAD_POOL_COUNT; i++)
{
INSTANT_POOLS[i] = new ThreadPoolExecutor(Config.THREADS_PER_INSTANT_THREAD_POOL, Config.THREADS_PER_INSTANT_THREAD_POOL, 0, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(100000));
}
// Prestart core threads.
for (ScheduledThreadPoolExecutor threadPool : SCHEDULED_POOLS)
{
threadPool.setRejectedExecutionHandler(new RejectedExecutionHandlerImpl());
threadPool.setRemoveOnCancelPolicy(true);
threadPool.prestartAllCoreThreads();
}
for (ThreadPoolExecutor threadPool : INSTANT_POOLS)
{
threadPool.setRejectedExecutionHandler(new RejectedExecutionHandlerImpl());
threadPool.prestartAllCoreThreads();
}
// Set pool options.
SCHEDULED_POOL.setRejectedExecutionHandler(new RejectedExecutionHandlerImpl());
SCHEDULED_POOL.setRemoveOnCancelPolicy(true);
SCHEDULED_POOL.prestartAllCoreThreads();
INSTANT_POOL.setRejectedExecutionHandler(new RejectedExecutionHandlerImpl());
INSTANT_POOL.prestartAllCoreThreads();
// Launch purge task.
scheduleAtFixedRate(() ->
{
purge();
}, 600000, 600000);
}, 60000, 60000);
LOGGER.info("ThreadPool: Initialized");
LOGGER.info("..." + Config.SCHEDULED_THREAD_POOL_COUNT + " scheduled pool executors with " + (Config.SCHEDULED_THREAD_POOL_COUNT * Config.THREADS_PER_SCHEDULED_THREAD_POOL) + " total threads.");
LOGGER.info("..." + Config.INSTANT_THREAD_POOL_COUNT + " instant pool executors with " + (Config.INSTANT_THREAD_POOL_COUNT * Config.THREADS_PER_INSTANT_THREAD_POOL) + " total threads.");
LOGGER.info("...scheduled pool executor with " + Config.SCHEDULED_THREAD_POOL_COUNT + " total threads.");
LOGGER.info("...instant pool executor with " + Config.INSTANT_THREAD_POOL_COUNT + " total threads.");
}
public static void purge()
{
for (ScheduledThreadPoolExecutor threadPool : SCHEDULED_POOLS)
{
threadPool.purge();
}
for (ThreadPoolExecutor threadPool : INSTANT_POOLS)
{
threadPool.purge();
}
SCHEDULED_POOL.purge();
INSTANT_POOL.purge();
}
/**
@ -102,16 +75,14 @@ public final class ThreadPool
*/
public static ScheduledFuture<?> schedule(Runnable runnable, long delay)
{
synchronized (SCHEDULED_POOLS)
try
{
try
{
return SCHEDULED_POOLS[SCHEDULED_THREAD_RANDOMIZER++ % Config.SCHEDULED_THREAD_POOL_COUNT].schedule(new RunnableWrapper(runnable), delay, TimeUnit.MILLISECONDS);
}
catch (Exception e)
{
return null;
}
return SCHEDULED_POOL.schedule(new RunnableWrapper(runnable), delay, TimeUnit.MILLISECONDS);
}
catch (Exception e)
{
LOGGER.warning(e.getMessage() + Config.EOL + e.getStackTrace());
return null;
}
}
@ -124,16 +95,14 @@ public final class ThreadPool
*/
public static ScheduledFuture<?> scheduleAtFixedRate(Runnable runnable, long initialDelay, long period)
{
synchronized (SCHEDULED_POOLS)
try
{
try
{
return SCHEDULED_POOLS[SCHEDULED_THREAD_RANDOMIZER++ % Config.SCHEDULED_THREAD_POOL_COUNT].scheduleAtFixedRate(new RunnableWrapper(runnable), initialDelay, period, TimeUnit.MILLISECONDS);
}
catch (Exception e)
{
return null;
}
return SCHEDULED_POOL.scheduleAtFixedRate(new RunnableWrapper(runnable), initialDelay, period, TimeUnit.MILLISECONDS);
}
catch (Exception e)
{
LOGGER.warning(e.getMessage() + Config.EOL + e.getStackTrace());
return null;
}
}
@ -143,50 +112,43 @@ public final class ThreadPool
*/
public static void execute(Runnable runnable)
{
synchronized (INSTANT_POOLS)
try
{
try
{
INSTANT_POOLS[INSTANT_THREAD_RANDOMIZER++ % Config.INSTANT_THREAD_POOL_COUNT].execute(new RunnableWrapper(runnable));
}
catch (Exception e)
{
}
INSTANT_POOL.execute(new RunnableWrapper(runnable));
}
catch (Exception e)
{
LOGGER.warning(e.getMessage() + Config.EOL + e.getStackTrace());
}
}
public static String[] getStats()
{
final String[] stats = new String[(SCHEDULED_POOLS.length + INSTANT_POOLS.length) * 10];
final String[] stats = new String[20];
int pos = 0;
for (int i = 0; i < SCHEDULED_POOLS.length; i++)
{
final ScheduledThreadPoolExecutor threadPool = SCHEDULED_POOLS[i];
stats[pos++] = "Scheduled pool #" + i + ":";
stats[pos++] = " |- ActiveCount: ...... " + threadPool.getActiveCount();
stats[pos++] = " |- CorePoolSize: ..... " + threadPool.getCorePoolSize();
stats[pos++] = " |- PoolSize: ......... " + threadPool.getPoolSize();
stats[pos++] = " |- LargestPoolSize: .. " + threadPool.getLargestPoolSize();
stats[pos++] = " |- MaximumPoolSize: .. " + threadPool.getMaximumPoolSize();
stats[pos++] = " |- CompletedTaskCount: " + threadPool.getCompletedTaskCount();
stats[pos++] = " |- QueuedTaskCount: .. " + threadPool.getQueue().size();
stats[pos++] = " |- TaskCount: ........ " + threadPool.getTaskCount();
stats[pos++] = " | -------";
}
for (int i = 0; i < INSTANT_POOLS.length; i++)
{
final ThreadPoolExecutor threadPool = INSTANT_POOLS[i];
stats[pos++] = "Instant pool #" + i + ":";
stats[pos++] = " |- ActiveCount: ...... " + threadPool.getActiveCount();
stats[pos++] = " |- CorePoolSize: ..... " + threadPool.getCorePoolSize();
stats[pos++] = " |- PoolSize: ......... " + threadPool.getPoolSize();
stats[pos++] = " |- LargestPoolSize: .. " + threadPool.getLargestPoolSize();
stats[pos++] = " |- MaximumPoolSize: .. " + threadPool.getMaximumPoolSize();
stats[pos++] = " |- CompletedTaskCount: " + threadPool.getCompletedTaskCount();
stats[pos++] = " |- QueuedTaskCount: .. " + threadPool.getQueue().size();
stats[pos++] = " |- TaskCount: ........ " + threadPool.getTaskCount();
stats[pos++] = " | -------";
}
stats[pos++] = "Scheduled pool:";
stats[pos++] = " |- ActiveCount: ...... " + SCHEDULED_POOL.getActiveCount();
stats[pos++] = " |- CorePoolSize: ..... " + SCHEDULED_POOL.getCorePoolSize();
stats[pos++] = " |- PoolSize: ......... " + SCHEDULED_POOL.getPoolSize();
stats[pos++] = " |- LargestPoolSize: .. " + SCHEDULED_POOL.getLargestPoolSize();
stats[pos++] = " |- MaximumPoolSize: .. " + SCHEDULED_POOL.getMaximumPoolSize();
stats[pos++] = " |- CompletedTaskCount: " + SCHEDULED_POOL.getCompletedTaskCount();
stats[pos++] = " |- QueuedTaskCount: .. " + SCHEDULED_POOL.getQueue().size();
stats[pos++] = " |- TaskCount: ........ " + SCHEDULED_POOL.getTaskCount();
stats[pos++] = " | -------";
stats[pos++] = "Instant pool:";
stats[pos++] = " |- ActiveCount: ...... " + INSTANT_POOL.getActiveCount();
stats[pos++] = " |- CorePoolSize: ..... " + INSTANT_POOL.getCorePoolSize();
stats[pos++] = " |- PoolSize: ......... " + INSTANT_POOL.getPoolSize();
stats[pos++] = " |- LargestPoolSize: .. " + INSTANT_POOL.getLargestPoolSize();
stats[pos++] = " |- MaximumPoolSize: .. " + INSTANT_POOL.getMaximumPoolSize();
stats[pos++] = " |- CompletedTaskCount: " + INSTANT_POOL.getCompletedTaskCount();
stats[pos++] = " |- QueuedTaskCount: .. " + INSTANT_POOL.getQueue().size();
stats[pos++] = " |- TaskCount: ........ " + INSTANT_POOL.getTaskCount();
stats[pos++] = " | -------";
return stats;
}
@ -198,14 +160,8 @@ public final class ThreadPool
try
{
LOGGER.info("ThreadPool: Shutting down.");
for (ScheduledThreadPoolExecutor threadPool : SCHEDULED_POOLS)
{
threadPool.shutdownNow();
}
for (ThreadPoolExecutor threadPool : INSTANT_POOLS)
{
threadPool.shutdownNow();
}
SCHEDULED_POOL.shutdownNow();
INSTANT_POOL.shutdownNow();
}
catch (Throwable t)
{

View File

@ -126,24 +126,16 @@ ServerListBrackets = False
# Thread Configuration
# ---------------------------------------------------------------------------
# Determines the amount of scheduled thread pools. If set to -1, the server will decide the amount depending on the available processors.
# Default: -1
ScheduledThreadPoolCount = -1
# Specifies how many threads will be in the scheduled pool.
# Default: 40
ScheduledThreadPoolCount = 40
# Specifies how many threads will be in a single scheduled pool.
# Default: 4
ThreadsPerScheduledThreadPool = 4
# Specifies how many threads will be in the single instant pool.
# Default: 20
InstantThreadPoolCount = 20
# Determines the amount of instant thread pools. If set to -1, the server will decide the amount depending on the available processors.
# Default: -1
InstantThreadPoolCount = -1
# Specifies how many threads will be in a single instant pool.
# Default: 2
ThreadsPerInstantThreadPool = 2
# Default: 2
UrgentPacketThreadCoreSize = 2
# Default: 20
UrgentPacketThreadCoreSize = 20
# Use threads to decrease startup time.
# Default: False

View File

@ -434,9 +434,7 @@ public final class Config
public static boolean ALT_DEV_SHOW_QUESTS_LOAD_IN_LOGS;
public static boolean ALT_DEV_SHOW_SCRIPTS_LOAD_IN_LOGS;
public static int SCHEDULED_THREAD_POOL_COUNT;
public static int THREADS_PER_SCHEDULED_THREAD_POOL;
public static int INSTANT_THREAD_POOL_COUNT;
public static int THREADS_PER_INSTANT_THREAD_POOL;
public static int IO_PACKET_THREAD_CORE_SIZE;
public static boolean THREADS_FOR_LOADING;
public static boolean DEADLOCK_DETECTOR;
@ -1297,19 +1295,9 @@ public final class Config
SERVER_LIST_AGE = serverSettings.getInt("ServerListAge", 0);
SERVER_LIST_BRACKET = serverSettings.getBoolean("ServerListBrackets", false);
SCHEDULED_THREAD_POOL_COUNT = serverSettings.getInt("ScheduledThreadPoolCount", -1);
if (SCHEDULED_THREAD_POOL_COUNT == -1)
{
SCHEDULED_THREAD_POOL_COUNT = Runtime.getRuntime().availableProcessors();
}
THREADS_PER_SCHEDULED_THREAD_POOL = serverSettings.getInt("ThreadsPerScheduledThreadPool", 4);
INSTANT_THREAD_POOL_COUNT = serverSettings.getInt("InstantThreadPoolCount", -1);
if (INSTANT_THREAD_POOL_COUNT == -1)
{
INSTANT_THREAD_POOL_COUNT = Runtime.getRuntime().availableProcessors();
}
THREADS_PER_INSTANT_THREAD_POOL = serverSettings.getInt("ThreadsPerInstantThreadPool", 2);
IO_PACKET_THREAD_CORE_SIZE = serverSettings.getInt("UrgentPacketThreadCoreSize", 2);
SCHEDULED_THREAD_POOL_COUNT = serverSettings.getInt("ScheduledThreadPoolCount", 40);
INSTANT_THREAD_POOL_COUNT = serverSettings.getInt("InstantThreadPoolCount", 20);
IO_PACKET_THREAD_CORE_SIZE = serverSettings.getInt("UrgentPacketThreadCoreSize", 20);
THREADS_FOR_LOADING = serverSettings.getBoolean("ThreadsForLoading", false);
DEADLOCK_DETECTOR = serverSettings.getBoolean("DeadLockDetector", true);

View File

@ -16,13 +16,17 @@
*/
package org.l2jmobius.commons.concurrent;
import java.lang.Thread.UncaughtExceptionHandler;
import java.util.logging.Logger;
import org.l2jmobius.Config;
/**
* @author UnAfraid
* @author Mobius
*/
public final class RunnableWrapper implements Runnable
{
private static final Logger LOGGER = Logger.getLogger(RunnableWrapper.class.getName());
private final Runnable _runnable;
public RunnableWrapper(Runnable runnable)
@ -37,14 +41,9 @@ public final class RunnableWrapper implements Runnable
{
_runnable.run();
}
catch (Throwable e)
catch (Exception e)
{
final Thread t = Thread.currentThread();
final UncaughtExceptionHandler h = t.getUncaughtExceptionHandler();
if (h != null)
{
h.uncaughtException(t, e);
}
LOGGER.warning(e.getMessage() + Config.EOL + e.getStackTrace());
}
}
}

View File

@ -26,10 +26,9 @@ import java.util.logging.Logger;
import org.l2jmobius.Config;
/**
* This class handles thread pooling system. It relies on two ThreadPoolExecutor arrays, which poolers number is generated using config.
* <p>
* Those arrays hold following pools:
* </p>
* This class handles thread pooling system.<br>
* It relies on two threadpool executors, which pool size is set using config.<br>
* Those arrays hold following pools:<br>
* <ul>
* <li>Scheduled pool keeps a track about incoming, future events.</li>
* <li>Instant pool handles short-life events.</li>
@ -39,59 +38,33 @@ public final class ThreadPool
{
private static final Logger LOGGER = Logger.getLogger(ThreadPool.class.getName());
private static ScheduledThreadPoolExecutor[] SCHEDULED_POOLS = new ScheduledThreadPoolExecutor[Config.SCHEDULED_THREAD_POOL_COUNT];
private static ThreadPoolExecutor[] INSTANT_POOLS = new ThreadPoolExecutor[Config.INSTANT_THREAD_POOL_COUNT];
private static volatile int SCHEDULED_THREAD_RANDOMIZER = 0;
private static volatile int INSTANT_THREAD_RANDOMIZER = 0;
private static final ScheduledThreadPoolExecutor SCHEDULED_POOL = new ScheduledThreadPoolExecutor(Config.SCHEDULED_THREAD_POOL_COUNT);
private static final ThreadPoolExecutor INSTANT_POOL = new ThreadPoolExecutor(Config.INSTANT_THREAD_POOL_COUNT, Config.INSTANT_THREAD_POOL_COUNT, 0, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(100000));
public static void init()
{
// Feed scheduled pool.
for (int i = 0; i < Config.SCHEDULED_THREAD_POOL_COUNT; i++)
{
SCHEDULED_POOLS[i] = new ScheduledThreadPoolExecutor(Config.THREADS_PER_SCHEDULED_THREAD_POOL);
}
// Feed instant pool.
for (int i = 0; i < Config.INSTANT_THREAD_POOL_COUNT; i++)
{
INSTANT_POOLS[i] = new ThreadPoolExecutor(Config.THREADS_PER_INSTANT_THREAD_POOL, Config.THREADS_PER_INSTANT_THREAD_POOL, 0, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(100000));
}
// Prestart core threads.
for (ScheduledThreadPoolExecutor threadPool : SCHEDULED_POOLS)
{
threadPool.setRejectedExecutionHandler(new RejectedExecutionHandlerImpl());
threadPool.setRemoveOnCancelPolicy(true);
threadPool.prestartAllCoreThreads();
}
for (ThreadPoolExecutor threadPool : INSTANT_POOLS)
{
threadPool.setRejectedExecutionHandler(new RejectedExecutionHandlerImpl());
threadPool.prestartAllCoreThreads();
}
// Set pool options.
SCHEDULED_POOL.setRejectedExecutionHandler(new RejectedExecutionHandlerImpl());
SCHEDULED_POOL.setRemoveOnCancelPolicy(true);
SCHEDULED_POOL.prestartAllCoreThreads();
INSTANT_POOL.setRejectedExecutionHandler(new RejectedExecutionHandlerImpl());
INSTANT_POOL.prestartAllCoreThreads();
// Launch purge task.
scheduleAtFixedRate(() ->
{
purge();
}, 600000, 600000);
}, 60000, 60000);
LOGGER.info("ThreadPool: Initialized");
LOGGER.info("..." + Config.SCHEDULED_THREAD_POOL_COUNT + " scheduled pool executors with " + (Config.SCHEDULED_THREAD_POOL_COUNT * Config.THREADS_PER_SCHEDULED_THREAD_POOL) + " total threads.");
LOGGER.info("..." + Config.INSTANT_THREAD_POOL_COUNT + " instant pool executors with " + (Config.INSTANT_THREAD_POOL_COUNT * Config.THREADS_PER_INSTANT_THREAD_POOL) + " total threads.");
LOGGER.info("...scheduled pool executor with " + Config.SCHEDULED_THREAD_POOL_COUNT + " total threads.");
LOGGER.info("...instant pool executor with " + Config.INSTANT_THREAD_POOL_COUNT + " total threads.");
}
public static void purge()
{
for (ScheduledThreadPoolExecutor threadPool : SCHEDULED_POOLS)
{
threadPool.purge();
}
for (ThreadPoolExecutor threadPool : INSTANT_POOLS)
{
threadPool.purge();
}
SCHEDULED_POOL.purge();
INSTANT_POOL.purge();
}
/**
@ -102,16 +75,14 @@ public final class ThreadPool
*/
public static ScheduledFuture<?> schedule(Runnable runnable, long delay)
{
synchronized (SCHEDULED_POOLS)
try
{
try
{
return SCHEDULED_POOLS[SCHEDULED_THREAD_RANDOMIZER++ % Config.SCHEDULED_THREAD_POOL_COUNT].schedule(new RunnableWrapper(runnable), delay, TimeUnit.MILLISECONDS);
}
catch (Exception e)
{
return null;
}
return SCHEDULED_POOL.schedule(new RunnableWrapper(runnable), delay, TimeUnit.MILLISECONDS);
}
catch (Exception e)
{
LOGGER.warning(e.getMessage() + Config.EOL + e.getStackTrace());
return null;
}
}
@ -124,16 +95,14 @@ public final class ThreadPool
*/
public static ScheduledFuture<?> scheduleAtFixedRate(Runnable runnable, long initialDelay, long period)
{
synchronized (SCHEDULED_POOLS)
try
{
try
{
return SCHEDULED_POOLS[SCHEDULED_THREAD_RANDOMIZER++ % Config.SCHEDULED_THREAD_POOL_COUNT].scheduleAtFixedRate(new RunnableWrapper(runnable), initialDelay, period, TimeUnit.MILLISECONDS);
}
catch (Exception e)
{
return null;
}
return SCHEDULED_POOL.scheduleAtFixedRate(new RunnableWrapper(runnable), initialDelay, period, TimeUnit.MILLISECONDS);
}
catch (Exception e)
{
LOGGER.warning(e.getMessage() + Config.EOL + e.getStackTrace());
return null;
}
}
@ -143,50 +112,43 @@ public final class ThreadPool
*/
public static void execute(Runnable runnable)
{
synchronized (INSTANT_POOLS)
try
{
try
{
INSTANT_POOLS[INSTANT_THREAD_RANDOMIZER++ % Config.INSTANT_THREAD_POOL_COUNT].execute(new RunnableWrapper(runnable));
}
catch (Exception e)
{
}
INSTANT_POOL.execute(new RunnableWrapper(runnable));
}
catch (Exception e)
{
LOGGER.warning(e.getMessage() + Config.EOL + e.getStackTrace());
}
}
public static String[] getStats()
{
final String[] stats = new String[(SCHEDULED_POOLS.length + INSTANT_POOLS.length) * 10];
final String[] stats = new String[20];
int pos = 0;
for (int i = 0; i < SCHEDULED_POOLS.length; i++)
{
final ScheduledThreadPoolExecutor threadPool = SCHEDULED_POOLS[i];
stats[pos++] = "Scheduled pool #" + i + ":";
stats[pos++] = " |- ActiveCount: ...... " + threadPool.getActiveCount();
stats[pos++] = " |- CorePoolSize: ..... " + threadPool.getCorePoolSize();
stats[pos++] = " |- PoolSize: ......... " + threadPool.getPoolSize();
stats[pos++] = " |- LargestPoolSize: .. " + threadPool.getLargestPoolSize();
stats[pos++] = " |- MaximumPoolSize: .. " + threadPool.getMaximumPoolSize();
stats[pos++] = " |- CompletedTaskCount: " + threadPool.getCompletedTaskCount();
stats[pos++] = " |- QueuedTaskCount: .. " + threadPool.getQueue().size();
stats[pos++] = " |- TaskCount: ........ " + threadPool.getTaskCount();
stats[pos++] = " | -------";
}
for (int i = 0; i < INSTANT_POOLS.length; i++)
{
final ThreadPoolExecutor threadPool = INSTANT_POOLS[i];
stats[pos++] = "Instant pool #" + i + ":";
stats[pos++] = " |- ActiveCount: ...... " + threadPool.getActiveCount();
stats[pos++] = " |- CorePoolSize: ..... " + threadPool.getCorePoolSize();
stats[pos++] = " |- PoolSize: ......... " + threadPool.getPoolSize();
stats[pos++] = " |- LargestPoolSize: .. " + threadPool.getLargestPoolSize();
stats[pos++] = " |- MaximumPoolSize: .. " + threadPool.getMaximumPoolSize();
stats[pos++] = " |- CompletedTaskCount: " + threadPool.getCompletedTaskCount();
stats[pos++] = " |- QueuedTaskCount: .. " + threadPool.getQueue().size();
stats[pos++] = " |- TaskCount: ........ " + threadPool.getTaskCount();
stats[pos++] = " | -------";
}
stats[pos++] = "Scheduled pool:";
stats[pos++] = " |- ActiveCount: ...... " + SCHEDULED_POOL.getActiveCount();
stats[pos++] = " |- CorePoolSize: ..... " + SCHEDULED_POOL.getCorePoolSize();
stats[pos++] = " |- PoolSize: ......... " + SCHEDULED_POOL.getPoolSize();
stats[pos++] = " |- LargestPoolSize: .. " + SCHEDULED_POOL.getLargestPoolSize();
stats[pos++] = " |- MaximumPoolSize: .. " + SCHEDULED_POOL.getMaximumPoolSize();
stats[pos++] = " |- CompletedTaskCount: " + SCHEDULED_POOL.getCompletedTaskCount();
stats[pos++] = " |- QueuedTaskCount: .. " + SCHEDULED_POOL.getQueue().size();
stats[pos++] = " |- TaskCount: ........ " + SCHEDULED_POOL.getTaskCount();
stats[pos++] = " | -------";
stats[pos++] = "Instant pool:";
stats[pos++] = " |- ActiveCount: ...... " + INSTANT_POOL.getActiveCount();
stats[pos++] = " |- CorePoolSize: ..... " + INSTANT_POOL.getCorePoolSize();
stats[pos++] = " |- PoolSize: ......... " + INSTANT_POOL.getPoolSize();
stats[pos++] = " |- LargestPoolSize: .. " + INSTANT_POOL.getLargestPoolSize();
stats[pos++] = " |- MaximumPoolSize: .. " + INSTANT_POOL.getMaximumPoolSize();
stats[pos++] = " |- CompletedTaskCount: " + INSTANT_POOL.getCompletedTaskCount();
stats[pos++] = " |- QueuedTaskCount: .. " + INSTANT_POOL.getQueue().size();
stats[pos++] = " |- TaskCount: ........ " + INSTANT_POOL.getTaskCount();
stats[pos++] = " | -------";
return stats;
}
@ -198,14 +160,8 @@ public final class ThreadPool
try
{
LOGGER.info("ThreadPool: Shutting down.");
for (ScheduledThreadPoolExecutor threadPool : SCHEDULED_POOLS)
{
threadPool.shutdownNow();
}
for (ThreadPoolExecutor threadPool : INSTANT_POOLS)
{
threadPool.shutdownNow();
}
SCHEDULED_POOL.shutdownNow();
INSTANT_POOL.shutdownNow();
}
catch (Throwable t)
{

View File

@ -126,24 +126,16 @@ ServerListBrackets = False
# Thread Configuration
# ---------------------------------------------------------------------------
# Determines the amount of scheduled thread pools. If set to -1, the server will decide the amount depending on the available processors.
# Default: -1
ScheduledThreadPoolCount = -1
# Specifies how many threads will be in the scheduled pool.
# Default: 40
ScheduledThreadPoolCount = 40
# Specifies how many threads will be in a single scheduled pool.
# Default: 4
ThreadsPerScheduledThreadPool = 4
# Specifies how many threads will be in the single instant pool.
# Default: 20
InstantThreadPoolCount = 20
# Determines the amount of instant thread pools. If set to -1, the server will decide the amount depending on the available processors.
# Default: -1
InstantThreadPoolCount = -1
# Specifies how many threads will be in a single instant pool.
# Default: 2
ThreadsPerInstantThreadPool = 2
# Default: 2
UrgentPacketThreadCoreSize = 2
# Default: 20
UrgentPacketThreadCoreSize = 20
# Use threads to decrease startup time.
# Default: False

View File

@ -434,9 +434,7 @@ public final class Config
public static boolean ALT_DEV_SHOW_QUESTS_LOAD_IN_LOGS;
public static boolean ALT_DEV_SHOW_SCRIPTS_LOAD_IN_LOGS;
public static int SCHEDULED_THREAD_POOL_COUNT;
public static int THREADS_PER_SCHEDULED_THREAD_POOL;
public static int INSTANT_THREAD_POOL_COUNT;
public static int THREADS_PER_INSTANT_THREAD_POOL;
public static int IO_PACKET_THREAD_CORE_SIZE;
public static boolean THREADS_FOR_LOADING;
public static boolean DEADLOCK_DETECTOR;
@ -1297,19 +1295,9 @@ public final class Config
SERVER_LIST_AGE = serverSettings.getInt("ServerListAge", 0);
SERVER_LIST_BRACKET = serverSettings.getBoolean("ServerListBrackets", false);
SCHEDULED_THREAD_POOL_COUNT = serverSettings.getInt("ScheduledThreadPoolCount", -1);
if (SCHEDULED_THREAD_POOL_COUNT == -1)
{
SCHEDULED_THREAD_POOL_COUNT = Runtime.getRuntime().availableProcessors();
}
THREADS_PER_SCHEDULED_THREAD_POOL = serverSettings.getInt("ThreadsPerScheduledThreadPool", 4);
INSTANT_THREAD_POOL_COUNT = serverSettings.getInt("InstantThreadPoolCount", -1);
if (INSTANT_THREAD_POOL_COUNT == -1)
{
INSTANT_THREAD_POOL_COUNT = Runtime.getRuntime().availableProcessors();
}
THREADS_PER_INSTANT_THREAD_POOL = serverSettings.getInt("ThreadsPerInstantThreadPool", 2);
IO_PACKET_THREAD_CORE_SIZE = serverSettings.getInt("UrgentPacketThreadCoreSize", 2);
SCHEDULED_THREAD_POOL_COUNT = serverSettings.getInt("ScheduledThreadPoolCount", 40);
INSTANT_THREAD_POOL_COUNT = serverSettings.getInt("InstantThreadPoolCount", 20);
IO_PACKET_THREAD_CORE_SIZE = serverSettings.getInt("UrgentPacketThreadCoreSize", 20);
THREADS_FOR_LOADING = serverSettings.getBoolean("ThreadsForLoading", false);
DEADLOCK_DETECTOR = serverSettings.getBoolean("DeadLockDetector", true);

View File

@ -16,13 +16,17 @@
*/
package org.l2jmobius.commons.concurrent;
import java.lang.Thread.UncaughtExceptionHandler;
import java.util.logging.Logger;
import org.l2jmobius.Config;
/**
* @author UnAfraid
* @author Mobius
*/
public final class RunnableWrapper implements Runnable
{
private static final Logger LOGGER = Logger.getLogger(RunnableWrapper.class.getName());
private final Runnable _runnable;
public RunnableWrapper(Runnable runnable)
@ -37,14 +41,9 @@ public final class RunnableWrapper implements Runnable
{
_runnable.run();
}
catch (Throwable e)
catch (Exception e)
{
final Thread t = Thread.currentThread();
final UncaughtExceptionHandler h = t.getUncaughtExceptionHandler();
if (h != null)
{
h.uncaughtException(t, e);
}
LOGGER.warning(e.getMessage() + Config.EOL + e.getStackTrace());
}
}
}

View File

@ -26,10 +26,9 @@ import java.util.logging.Logger;
import org.l2jmobius.Config;
/**
* This class handles thread pooling system. It relies on two ThreadPoolExecutor arrays, which poolers number is generated using config.
* <p>
* Those arrays hold following pools:
* </p>
* This class handles thread pooling system.<br>
* It relies on two threadpool executors, which pool size is set using config.<br>
* Those arrays hold following pools:<br>
* <ul>
* <li>Scheduled pool keeps a track about incoming, future events.</li>
* <li>Instant pool handles short-life events.</li>
@ -39,59 +38,33 @@ public final class ThreadPool
{
private static final Logger LOGGER = Logger.getLogger(ThreadPool.class.getName());
private static ScheduledThreadPoolExecutor[] SCHEDULED_POOLS = new ScheduledThreadPoolExecutor[Config.SCHEDULED_THREAD_POOL_COUNT];
private static ThreadPoolExecutor[] INSTANT_POOLS = new ThreadPoolExecutor[Config.INSTANT_THREAD_POOL_COUNT];
private static volatile int SCHEDULED_THREAD_RANDOMIZER = 0;
private static volatile int INSTANT_THREAD_RANDOMIZER = 0;
private static final ScheduledThreadPoolExecutor SCHEDULED_POOL = new ScheduledThreadPoolExecutor(Config.SCHEDULED_THREAD_POOL_COUNT);
private static final ThreadPoolExecutor INSTANT_POOL = new ThreadPoolExecutor(Config.INSTANT_THREAD_POOL_COUNT, Config.INSTANT_THREAD_POOL_COUNT, 0, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(100000));
public static void init()
{
// Feed scheduled pool.
for (int i = 0; i < Config.SCHEDULED_THREAD_POOL_COUNT; i++)
{
SCHEDULED_POOLS[i] = new ScheduledThreadPoolExecutor(Config.THREADS_PER_SCHEDULED_THREAD_POOL);
}
// Feed instant pool.
for (int i = 0; i < Config.INSTANT_THREAD_POOL_COUNT; i++)
{
INSTANT_POOLS[i] = new ThreadPoolExecutor(Config.THREADS_PER_INSTANT_THREAD_POOL, Config.THREADS_PER_INSTANT_THREAD_POOL, 0, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(100000));
}
// Prestart core threads.
for (ScheduledThreadPoolExecutor threadPool : SCHEDULED_POOLS)
{
threadPool.setRejectedExecutionHandler(new RejectedExecutionHandlerImpl());
threadPool.setRemoveOnCancelPolicy(true);
threadPool.prestartAllCoreThreads();
}
for (ThreadPoolExecutor threadPool : INSTANT_POOLS)
{
threadPool.setRejectedExecutionHandler(new RejectedExecutionHandlerImpl());
threadPool.prestartAllCoreThreads();
}
// Set pool options.
SCHEDULED_POOL.setRejectedExecutionHandler(new RejectedExecutionHandlerImpl());
SCHEDULED_POOL.setRemoveOnCancelPolicy(true);
SCHEDULED_POOL.prestartAllCoreThreads();
INSTANT_POOL.setRejectedExecutionHandler(new RejectedExecutionHandlerImpl());
INSTANT_POOL.prestartAllCoreThreads();
// Launch purge task.
scheduleAtFixedRate(() ->
{
purge();
}, 600000, 600000);
}, 60000, 60000);
LOGGER.info("ThreadPool: Initialized");
LOGGER.info("..." + Config.SCHEDULED_THREAD_POOL_COUNT + " scheduled pool executors with " + (Config.SCHEDULED_THREAD_POOL_COUNT * Config.THREADS_PER_SCHEDULED_THREAD_POOL) + " total threads.");
LOGGER.info("..." + Config.INSTANT_THREAD_POOL_COUNT + " instant pool executors with " + (Config.INSTANT_THREAD_POOL_COUNT * Config.THREADS_PER_INSTANT_THREAD_POOL) + " total threads.");
LOGGER.info("...scheduled pool executor with " + Config.SCHEDULED_THREAD_POOL_COUNT + " total threads.");
LOGGER.info("...instant pool executor with " + Config.INSTANT_THREAD_POOL_COUNT + " total threads.");
}
public static void purge()
{
for (ScheduledThreadPoolExecutor threadPool : SCHEDULED_POOLS)
{
threadPool.purge();
}
for (ThreadPoolExecutor threadPool : INSTANT_POOLS)
{
threadPool.purge();
}
SCHEDULED_POOL.purge();
INSTANT_POOL.purge();
}
/**
@ -102,16 +75,14 @@ public final class ThreadPool
*/
public static ScheduledFuture<?> schedule(Runnable runnable, long delay)
{
synchronized (SCHEDULED_POOLS)
try
{
try
{
return SCHEDULED_POOLS[SCHEDULED_THREAD_RANDOMIZER++ % Config.SCHEDULED_THREAD_POOL_COUNT].schedule(new RunnableWrapper(runnable), delay, TimeUnit.MILLISECONDS);
}
catch (Exception e)
{
return null;
}
return SCHEDULED_POOL.schedule(new RunnableWrapper(runnable), delay, TimeUnit.MILLISECONDS);
}
catch (Exception e)
{
LOGGER.warning(e.getMessage() + Config.EOL + e.getStackTrace());
return null;
}
}
@ -124,16 +95,14 @@ public final class ThreadPool
*/
public static ScheduledFuture<?> scheduleAtFixedRate(Runnable runnable, long initialDelay, long period)
{
synchronized (SCHEDULED_POOLS)
try
{
try
{
return SCHEDULED_POOLS[SCHEDULED_THREAD_RANDOMIZER++ % Config.SCHEDULED_THREAD_POOL_COUNT].scheduleAtFixedRate(new RunnableWrapper(runnable), initialDelay, period, TimeUnit.MILLISECONDS);
}
catch (Exception e)
{
return null;
}
return SCHEDULED_POOL.scheduleAtFixedRate(new RunnableWrapper(runnable), initialDelay, period, TimeUnit.MILLISECONDS);
}
catch (Exception e)
{
LOGGER.warning(e.getMessage() + Config.EOL + e.getStackTrace());
return null;
}
}
@ -143,50 +112,43 @@ public final class ThreadPool
*/
public static void execute(Runnable runnable)
{
synchronized (INSTANT_POOLS)
try
{
try
{
INSTANT_POOLS[INSTANT_THREAD_RANDOMIZER++ % Config.INSTANT_THREAD_POOL_COUNT].execute(new RunnableWrapper(runnable));
}
catch (Exception e)
{
}
INSTANT_POOL.execute(new RunnableWrapper(runnable));
}
catch (Exception e)
{
LOGGER.warning(e.getMessage() + Config.EOL + e.getStackTrace());
}
}
public static String[] getStats()
{
final String[] stats = new String[(SCHEDULED_POOLS.length + INSTANT_POOLS.length) * 10];
final String[] stats = new String[20];
int pos = 0;
for (int i = 0; i < SCHEDULED_POOLS.length; i++)
{
final ScheduledThreadPoolExecutor threadPool = SCHEDULED_POOLS[i];
stats[pos++] = "Scheduled pool #" + i + ":";
stats[pos++] = " |- ActiveCount: ...... " + threadPool.getActiveCount();
stats[pos++] = " |- CorePoolSize: ..... " + threadPool.getCorePoolSize();
stats[pos++] = " |- PoolSize: ......... " + threadPool.getPoolSize();
stats[pos++] = " |- LargestPoolSize: .. " + threadPool.getLargestPoolSize();
stats[pos++] = " |- MaximumPoolSize: .. " + threadPool.getMaximumPoolSize();
stats[pos++] = " |- CompletedTaskCount: " + threadPool.getCompletedTaskCount();
stats[pos++] = " |- QueuedTaskCount: .. " + threadPool.getQueue().size();
stats[pos++] = " |- TaskCount: ........ " + threadPool.getTaskCount();
stats[pos++] = " | -------";
}
for (int i = 0; i < INSTANT_POOLS.length; i++)
{
final ThreadPoolExecutor threadPool = INSTANT_POOLS[i];
stats[pos++] = "Instant pool #" + i + ":";
stats[pos++] = " |- ActiveCount: ...... " + threadPool.getActiveCount();
stats[pos++] = " |- CorePoolSize: ..... " + threadPool.getCorePoolSize();
stats[pos++] = " |- PoolSize: ......... " + threadPool.getPoolSize();
stats[pos++] = " |- LargestPoolSize: .. " + threadPool.getLargestPoolSize();
stats[pos++] = " |- MaximumPoolSize: .. " + threadPool.getMaximumPoolSize();
stats[pos++] = " |- CompletedTaskCount: " + threadPool.getCompletedTaskCount();
stats[pos++] = " |- QueuedTaskCount: .. " + threadPool.getQueue().size();
stats[pos++] = " |- TaskCount: ........ " + threadPool.getTaskCount();
stats[pos++] = " | -------";
}
stats[pos++] = "Scheduled pool:";
stats[pos++] = " |- ActiveCount: ...... " + SCHEDULED_POOL.getActiveCount();
stats[pos++] = " |- CorePoolSize: ..... " + SCHEDULED_POOL.getCorePoolSize();
stats[pos++] = " |- PoolSize: ......... " + SCHEDULED_POOL.getPoolSize();
stats[pos++] = " |- LargestPoolSize: .. " + SCHEDULED_POOL.getLargestPoolSize();
stats[pos++] = " |- MaximumPoolSize: .. " + SCHEDULED_POOL.getMaximumPoolSize();
stats[pos++] = " |- CompletedTaskCount: " + SCHEDULED_POOL.getCompletedTaskCount();
stats[pos++] = " |- QueuedTaskCount: .. " + SCHEDULED_POOL.getQueue().size();
stats[pos++] = " |- TaskCount: ........ " + SCHEDULED_POOL.getTaskCount();
stats[pos++] = " | -------";
stats[pos++] = "Instant pool:";
stats[pos++] = " |- ActiveCount: ...... " + INSTANT_POOL.getActiveCount();
stats[pos++] = " |- CorePoolSize: ..... " + INSTANT_POOL.getCorePoolSize();
stats[pos++] = " |- PoolSize: ......... " + INSTANT_POOL.getPoolSize();
stats[pos++] = " |- LargestPoolSize: .. " + INSTANT_POOL.getLargestPoolSize();
stats[pos++] = " |- MaximumPoolSize: .. " + INSTANT_POOL.getMaximumPoolSize();
stats[pos++] = " |- CompletedTaskCount: " + INSTANT_POOL.getCompletedTaskCount();
stats[pos++] = " |- QueuedTaskCount: .. " + INSTANT_POOL.getQueue().size();
stats[pos++] = " |- TaskCount: ........ " + INSTANT_POOL.getTaskCount();
stats[pos++] = " | -------";
return stats;
}
@ -198,14 +160,8 @@ public final class ThreadPool
try
{
LOGGER.info("ThreadPool: Shutting down.");
for (ScheduledThreadPoolExecutor threadPool : SCHEDULED_POOLS)
{
threadPool.shutdownNow();
}
for (ThreadPoolExecutor threadPool : INSTANT_POOLS)
{
threadPool.shutdownNow();
}
SCHEDULED_POOL.shutdownNow();
INSTANT_POOL.shutdownNow();
}
catch (Throwable t)
{

View File

@ -126,24 +126,16 @@ ServerListBrackets = False
# Thread Configuration
# ---------------------------------------------------------------------------
# Determines the amount of scheduled thread pools. If set to -1, the server will decide the amount depending on the available processors.
# Default: -1
ScheduledThreadPoolCount = -1
# Specifies how many threads will be in the scheduled pool.
# Default: 40
ScheduledThreadPoolCount = 40
# Specifies how many threads will be in a single scheduled pool.
# Default: 4
ThreadsPerScheduledThreadPool = 4
# Specifies how many threads will be in the single instant pool.
# Default: 20
InstantThreadPoolCount = 20
# Determines the amount of instant thread pools. If set to -1, the server will decide the amount depending on the available processors.
# Default: -1
InstantThreadPoolCount = -1
# Specifies how many threads will be in a single instant pool.
# Default: 2
ThreadsPerInstantThreadPool = 2
# Default: 2
UrgentPacketThreadCoreSize = 2
# Default: 20
UrgentPacketThreadCoreSize = 20
# Use threads to decrease startup time.
# Default: False

View File

@ -434,9 +434,7 @@ public final class Config
public static boolean ALT_DEV_SHOW_QUESTS_LOAD_IN_LOGS;
public static boolean ALT_DEV_SHOW_SCRIPTS_LOAD_IN_LOGS;
public static int SCHEDULED_THREAD_POOL_COUNT;
public static int THREADS_PER_SCHEDULED_THREAD_POOL;
public static int INSTANT_THREAD_POOL_COUNT;
public static int THREADS_PER_INSTANT_THREAD_POOL;
public static int IO_PACKET_THREAD_CORE_SIZE;
public static boolean THREADS_FOR_LOADING;
public static boolean DEADLOCK_DETECTOR;
@ -1297,19 +1295,9 @@ public final class Config
SERVER_LIST_AGE = serverSettings.getInt("ServerListAge", 0);
SERVER_LIST_BRACKET = serverSettings.getBoolean("ServerListBrackets", false);
SCHEDULED_THREAD_POOL_COUNT = serverSettings.getInt("ScheduledThreadPoolCount", -1);
if (SCHEDULED_THREAD_POOL_COUNT == -1)
{
SCHEDULED_THREAD_POOL_COUNT = Runtime.getRuntime().availableProcessors();
}
THREADS_PER_SCHEDULED_THREAD_POOL = serverSettings.getInt("ThreadsPerScheduledThreadPool", 4);
INSTANT_THREAD_POOL_COUNT = serverSettings.getInt("InstantThreadPoolCount", -1);
if (INSTANT_THREAD_POOL_COUNT == -1)
{
INSTANT_THREAD_POOL_COUNT = Runtime.getRuntime().availableProcessors();
}
THREADS_PER_INSTANT_THREAD_POOL = serverSettings.getInt("ThreadsPerInstantThreadPool", 2);
IO_PACKET_THREAD_CORE_SIZE = serverSettings.getInt("UrgentPacketThreadCoreSize", 2);
SCHEDULED_THREAD_POOL_COUNT = serverSettings.getInt("ScheduledThreadPoolCount", 40);
INSTANT_THREAD_POOL_COUNT = serverSettings.getInt("InstantThreadPoolCount", 20);
IO_PACKET_THREAD_CORE_SIZE = serverSettings.getInt("UrgentPacketThreadCoreSize", 20);
THREADS_FOR_LOADING = serverSettings.getBoolean("ThreadsForLoading", false);
DEADLOCK_DETECTOR = serverSettings.getBoolean("DeadLockDetector", true);

View File

@ -16,13 +16,17 @@
*/
package org.l2jmobius.commons.concurrent;
import java.lang.Thread.UncaughtExceptionHandler;
import java.util.logging.Logger;
import org.l2jmobius.Config;
/**
* @author UnAfraid
* @author Mobius
*/
public final class RunnableWrapper implements Runnable
{
private static final Logger LOGGER = Logger.getLogger(RunnableWrapper.class.getName());
private final Runnable _runnable;
public RunnableWrapper(Runnable runnable)
@ -37,14 +41,9 @@ public final class RunnableWrapper implements Runnable
{
_runnable.run();
}
catch (Throwable e)
catch (Exception e)
{
final Thread t = Thread.currentThread();
final UncaughtExceptionHandler h = t.getUncaughtExceptionHandler();
if (h != null)
{
h.uncaughtException(t, e);
}
LOGGER.warning(e.getMessage() + Config.EOL + e.getStackTrace());
}
}
}

View File

@ -26,10 +26,9 @@ import java.util.logging.Logger;
import org.l2jmobius.Config;
/**
* This class handles thread pooling system. It relies on two ThreadPoolExecutor arrays, which poolers number is generated using config.
* <p>
* Those arrays hold following pools:
* </p>
* This class handles thread pooling system.<br>
* It relies on two threadpool executors, which pool size is set using config.<br>
* Those arrays hold following pools:<br>
* <ul>
* <li>Scheduled pool keeps a track about incoming, future events.</li>
* <li>Instant pool handles short-life events.</li>
@ -39,59 +38,33 @@ public final class ThreadPool
{
private static final Logger LOGGER = Logger.getLogger(ThreadPool.class.getName());
private static ScheduledThreadPoolExecutor[] SCHEDULED_POOLS = new ScheduledThreadPoolExecutor[Config.SCHEDULED_THREAD_POOL_COUNT];
private static ThreadPoolExecutor[] INSTANT_POOLS = new ThreadPoolExecutor[Config.INSTANT_THREAD_POOL_COUNT];
private static volatile int SCHEDULED_THREAD_RANDOMIZER = 0;
private static volatile int INSTANT_THREAD_RANDOMIZER = 0;
private static final ScheduledThreadPoolExecutor SCHEDULED_POOL = new ScheduledThreadPoolExecutor(Config.SCHEDULED_THREAD_POOL_COUNT);
private static final ThreadPoolExecutor INSTANT_POOL = new ThreadPoolExecutor(Config.INSTANT_THREAD_POOL_COUNT, Config.INSTANT_THREAD_POOL_COUNT, 0, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(100000));
public static void init()
{
// Feed scheduled pool.
for (int i = 0; i < Config.SCHEDULED_THREAD_POOL_COUNT; i++)
{
SCHEDULED_POOLS[i] = new ScheduledThreadPoolExecutor(Config.THREADS_PER_SCHEDULED_THREAD_POOL);
}
// Feed instant pool.
for (int i = 0; i < Config.INSTANT_THREAD_POOL_COUNT; i++)
{
INSTANT_POOLS[i] = new ThreadPoolExecutor(Config.THREADS_PER_INSTANT_THREAD_POOL, Config.THREADS_PER_INSTANT_THREAD_POOL, 0, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(100000));
}
// Prestart core threads.
for (ScheduledThreadPoolExecutor threadPool : SCHEDULED_POOLS)
{
threadPool.setRejectedExecutionHandler(new RejectedExecutionHandlerImpl());
threadPool.setRemoveOnCancelPolicy(true);
threadPool.prestartAllCoreThreads();
}
for (ThreadPoolExecutor threadPool : INSTANT_POOLS)
{
threadPool.setRejectedExecutionHandler(new RejectedExecutionHandlerImpl());
threadPool.prestartAllCoreThreads();
}
// Set pool options.
SCHEDULED_POOL.setRejectedExecutionHandler(new RejectedExecutionHandlerImpl());
SCHEDULED_POOL.setRemoveOnCancelPolicy(true);
SCHEDULED_POOL.prestartAllCoreThreads();
INSTANT_POOL.setRejectedExecutionHandler(new RejectedExecutionHandlerImpl());
INSTANT_POOL.prestartAllCoreThreads();
// Launch purge task.
scheduleAtFixedRate(() ->
{
purge();
}, 600000, 600000);
}, 60000, 60000);
LOGGER.info("ThreadPool: Initialized");
LOGGER.info("..." + Config.SCHEDULED_THREAD_POOL_COUNT + " scheduled pool executors with " + (Config.SCHEDULED_THREAD_POOL_COUNT * Config.THREADS_PER_SCHEDULED_THREAD_POOL) + " total threads.");
LOGGER.info("..." + Config.INSTANT_THREAD_POOL_COUNT + " instant pool executors with " + (Config.INSTANT_THREAD_POOL_COUNT * Config.THREADS_PER_INSTANT_THREAD_POOL) + " total threads.");
LOGGER.info("...scheduled pool executor with " + Config.SCHEDULED_THREAD_POOL_COUNT + " total threads.");
LOGGER.info("...instant pool executor with " + Config.INSTANT_THREAD_POOL_COUNT + " total threads.");
}
public static void purge()
{
for (ScheduledThreadPoolExecutor threadPool : SCHEDULED_POOLS)
{
threadPool.purge();
}
for (ThreadPoolExecutor threadPool : INSTANT_POOLS)
{
threadPool.purge();
}
SCHEDULED_POOL.purge();
INSTANT_POOL.purge();
}
/**
@ -102,16 +75,14 @@ public final class ThreadPool
*/
public static ScheduledFuture<?> schedule(Runnable runnable, long delay)
{
synchronized (SCHEDULED_POOLS)
try
{
try
{
return SCHEDULED_POOLS[SCHEDULED_THREAD_RANDOMIZER++ % Config.SCHEDULED_THREAD_POOL_COUNT].schedule(new RunnableWrapper(runnable), delay, TimeUnit.MILLISECONDS);
}
catch (Exception e)
{
return null;
}
return SCHEDULED_POOL.schedule(new RunnableWrapper(runnable), delay, TimeUnit.MILLISECONDS);
}
catch (Exception e)
{
LOGGER.warning(e.getMessage() + Config.EOL + e.getStackTrace());
return null;
}
}
@ -124,16 +95,14 @@ public final class ThreadPool
*/
public static ScheduledFuture<?> scheduleAtFixedRate(Runnable runnable, long initialDelay, long period)
{
synchronized (SCHEDULED_POOLS)
try
{
try
{
return SCHEDULED_POOLS[SCHEDULED_THREAD_RANDOMIZER++ % Config.SCHEDULED_THREAD_POOL_COUNT].scheduleAtFixedRate(new RunnableWrapper(runnable), initialDelay, period, TimeUnit.MILLISECONDS);
}
catch (Exception e)
{
return null;
}
return SCHEDULED_POOL.scheduleAtFixedRate(new RunnableWrapper(runnable), initialDelay, period, TimeUnit.MILLISECONDS);
}
catch (Exception e)
{
LOGGER.warning(e.getMessage() + Config.EOL + e.getStackTrace());
return null;
}
}
@ -143,50 +112,43 @@ public final class ThreadPool
*/
public static void execute(Runnable runnable)
{
synchronized (INSTANT_POOLS)
try
{
try
{
INSTANT_POOLS[INSTANT_THREAD_RANDOMIZER++ % Config.INSTANT_THREAD_POOL_COUNT].execute(new RunnableWrapper(runnable));
}
catch (Exception e)
{
}
INSTANT_POOL.execute(new RunnableWrapper(runnable));
}
catch (Exception e)
{
LOGGER.warning(e.getMessage() + Config.EOL + e.getStackTrace());
}
}
public static String[] getStats()
{
final String[] stats = new String[(SCHEDULED_POOLS.length + INSTANT_POOLS.length) * 10];
final String[] stats = new String[20];
int pos = 0;
for (int i = 0; i < SCHEDULED_POOLS.length; i++)
{
final ScheduledThreadPoolExecutor threadPool = SCHEDULED_POOLS[i];
stats[pos++] = "Scheduled pool #" + i + ":";
stats[pos++] = " |- ActiveCount: ...... " + threadPool.getActiveCount();
stats[pos++] = " |- CorePoolSize: ..... " + threadPool.getCorePoolSize();
stats[pos++] = " |- PoolSize: ......... " + threadPool.getPoolSize();
stats[pos++] = " |- LargestPoolSize: .. " + threadPool.getLargestPoolSize();
stats[pos++] = " |- MaximumPoolSize: .. " + threadPool.getMaximumPoolSize();
stats[pos++] = " |- CompletedTaskCount: " + threadPool.getCompletedTaskCount();
stats[pos++] = " |- QueuedTaskCount: .. " + threadPool.getQueue().size();
stats[pos++] = " |- TaskCount: ........ " + threadPool.getTaskCount();
stats[pos++] = " | -------";
}
for (int i = 0; i < INSTANT_POOLS.length; i++)
{
final ThreadPoolExecutor threadPool = INSTANT_POOLS[i];
stats[pos++] = "Instant pool #" + i + ":";
stats[pos++] = " |- ActiveCount: ...... " + threadPool.getActiveCount();
stats[pos++] = " |- CorePoolSize: ..... " + threadPool.getCorePoolSize();
stats[pos++] = " |- PoolSize: ......... " + threadPool.getPoolSize();
stats[pos++] = " |- LargestPoolSize: .. " + threadPool.getLargestPoolSize();
stats[pos++] = " |- MaximumPoolSize: .. " + threadPool.getMaximumPoolSize();
stats[pos++] = " |- CompletedTaskCount: " + threadPool.getCompletedTaskCount();
stats[pos++] = " |- QueuedTaskCount: .. " + threadPool.getQueue().size();
stats[pos++] = " |- TaskCount: ........ " + threadPool.getTaskCount();
stats[pos++] = " | -------";
}
stats[pos++] = "Scheduled pool:";
stats[pos++] = " |- ActiveCount: ...... " + SCHEDULED_POOL.getActiveCount();
stats[pos++] = " |- CorePoolSize: ..... " + SCHEDULED_POOL.getCorePoolSize();
stats[pos++] = " |- PoolSize: ......... " + SCHEDULED_POOL.getPoolSize();
stats[pos++] = " |- LargestPoolSize: .. " + SCHEDULED_POOL.getLargestPoolSize();
stats[pos++] = " |- MaximumPoolSize: .. " + SCHEDULED_POOL.getMaximumPoolSize();
stats[pos++] = " |- CompletedTaskCount: " + SCHEDULED_POOL.getCompletedTaskCount();
stats[pos++] = " |- QueuedTaskCount: .. " + SCHEDULED_POOL.getQueue().size();
stats[pos++] = " |- TaskCount: ........ " + SCHEDULED_POOL.getTaskCount();
stats[pos++] = " | -------";
stats[pos++] = "Instant pool:";
stats[pos++] = " |- ActiveCount: ...... " + INSTANT_POOL.getActiveCount();
stats[pos++] = " |- CorePoolSize: ..... " + INSTANT_POOL.getCorePoolSize();
stats[pos++] = " |- PoolSize: ......... " + INSTANT_POOL.getPoolSize();
stats[pos++] = " |- LargestPoolSize: .. " + INSTANT_POOL.getLargestPoolSize();
stats[pos++] = " |- MaximumPoolSize: .. " + INSTANT_POOL.getMaximumPoolSize();
stats[pos++] = " |- CompletedTaskCount: " + INSTANT_POOL.getCompletedTaskCount();
stats[pos++] = " |- QueuedTaskCount: .. " + INSTANT_POOL.getQueue().size();
stats[pos++] = " |- TaskCount: ........ " + INSTANT_POOL.getTaskCount();
stats[pos++] = " | -------";
return stats;
}
@ -198,14 +160,8 @@ public final class ThreadPool
try
{
LOGGER.info("ThreadPool: Shutting down.");
for (ScheduledThreadPoolExecutor threadPool : SCHEDULED_POOLS)
{
threadPool.shutdownNow();
}
for (ThreadPoolExecutor threadPool : INSTANT_POOLS)
{
threadPool.shutdownNow();
}
SCHEDULED_POOL.shutdownNow();
INSTANT_POOL.shutdownNow();
}
catch (Throwable t)
{

View File

@ -126,24 +126,16 @@ ServerListBrackets = False
# Thread Configuration
# ---------------------------------------------------------------------------
# Determines the amount of scheduled thread pools. If set to -1, the server will decide the amount depending on the available processors.
# Default: -1
ScheduledThreadPoolCount = -1
# Specifies how many threads will be in the scheduled pool.
# Default: 40
ScheduledThreadPoolCount = 40
# Specifies how many threads will be in a single scheduled pool.
# Default: 4
ThreadsPerScheduledThreadPool = 4
# Specifies how many threads will be in the single instant pool.
# Default: 20
InstantThreadPoolCount = 20
# Determines the amount of instant thread pools. If set to -1, the server will decide the amount depending on the available processors.
# Default: -1
InstantThreadPoolCount = -1
# Specifies how many threads will be in a single instant pool.
# Default: 2
ThreadsPerInstantThreadPool = 2
# Default: 2
UrgentPacketThreadCoreSize = 2
# Default: 20
UrgentPacketThreadCoreSize = 20
# Use threads to decrease startup time.
# Default: False

View File

@ -434,9 +434,7 @@ public final class Config
public static boolean ALT_DEV_SHOW_QUESTS_LOAD_IN_LOGS;
public static boolean ALT_DEV_SHOW_SCRIPTS_LOAD_IN_LOGS;
public static int SCHEDULED_THREAD_POOL_COUNT;
public static int THREADS_PER_SCHEDULED_THREAD_POOL;
public static int INSTANT_THREAD_POOL_COUNT;
public static int THREADS_PER_INSTANT_THREAD_POOL;
public static int IO_PACKET_THREAD_CORE_SIZE;
public static boolean THREADS_FOR_LOADING;
public static boolean DEADLOCK_DETECTOR;
@ -1297,19 +1295,9 @@ public final class Config
SERVER_LIST_AGE = serverSettings.getInt("ServerListAge", 0);
SERVER_LIST_BRACKET = serverSettings.getBoolean("ServerListBrackets", false);
SCHEDULED_THREAD_POOL_COUNT = serverSettings.getInt("ScheduledThreadPoolCount", -1);
if (SCHEDULED_THREAD_POOL_COUNT == -1)
{
SCHEDULED_THREAD_POOL_COUNT = Runtime.getRuntime().availableProcessors();
}
THREADS_PER_SCHEDULED_THREAD_POOL = serverSettings.getInt("ThreadsPerScheduledThreadPool", 4);
INSTANT_THREAD_POOL_COUNT = serverSettings.getInt("InstantThreadPoolCount", -1);
if (INSTANT_THREAD_POOL_COUNT == -1)
{
INSTANT_THREAD_POOL_COUNT = Runtime.getRuntime().availableProcessors();
}
THREADS_PER_INSTANT_THREAD_POOL = serverSettings.getInt("ThreadsPerInstantThreadPool", 2);
IO_PACKET_THREAD_CORE_SIZE = serverSettings.getInt("UrgentPacketThreadCoreSize", 2);
SCHEDULED_THREAD_POOL_COUNT = serverSettings.getInt("ScheduledThreadPoolCount", 40);
INSTANT_THREAD_POOL_COUNT = serverSettings.getInt("InstantThreadPoolCount", 20);
IO_PACKET_THREAD_CORE_SIZE = serverSettings.getInt("UrgentPacketThreadCoreSize", 20);
THREADS_FOR_LOADING = serverSettings.getBoolean("ThreadsForLoading", false);
DEADLOCK_DETECTOR = serverSettings.getBoolean("DeadLockDetector", true);

View File

@ -16,13 +16,17 @@
*/
package org.l2jmobius.commons.concurrent;
import java.lang.Thread.UncaughtExceptionHandler;
import java.util.logging.Logger;
import org.l2jmobius.Config;
/**
* @author UnAfraid
* @author Mobius
*/
public final class RunnableWrapper implements Runnable
{
private static final Logger LOGGER = Logger.getLogger(RunnableWrapper.class.getName());
private final Runnable _runnable;
public RunnableWrapper(Runnable runnable)
@ -37,14 +41,9 @@ public final class RunnableWrapper implements Runnable
{
_runnable.run();
}
catch (Throwable e)
catch (Exception e)
{
final Thread t = Thread.currentThread();
final UncaughtExceptionHandler h = t.getUncaughtExceptionHandler();
if (h != null)
{
h.uncaughtException(t, e);
}
LOGGER.warning(e.getMessage() + Config.EOL + e.getStackTrace());
}
}
}

View File

@ -26,10 +26,9 @@ import java.util.logging.Logger;
import org.l2jmobius.Config;
/**
* This class handles thread pooling system. It relies on two ThreadPoolExecutor arrays, which poolers number is generated using config.
* <p>
* Those arrays hold following pools:
* </p>
* This class handles thread pooling system.<br>
* It relies on two threadpool executors, which pool size is set using config.<br>
* Those arrays hold following pools:<br>
* <ul>
* <li>Scheduled pool keeps a track about incoming, future events.</li>
* <li>Instant pool handles short-life events.</li>
@ -39,59 +38,33 @@ public final class ThreadPool
{
private static final Logger LOGGER = Logger.getLogger(ThreadPool.class.getName());
private static ScheduledThreadPoolExecutor[] SCHEDULED_POOLS = new ScheduledThreadPoolExecutor[Config.SCHEDULED_THREAD_POOL_COUNT];
private static ThreadPoolExecutor[] INSTANT_POOLS = new ThreadPoolExecutor[Config.INSTANT_THREAD_POOL_COUNT];
private static volatile int SCHEDULED_THREAD_RANDOMIZER = 0;
private static volatile int INSTANT_THREAD_RANDOMIZER = 0;
private static final ScheduledThreadPoolExecutor SCHEDULED_POOL = new ScheduledThreadPoolExecutor(Config.SCHEDULED_THREAD_POOL_COUNT);
private static final ThreadPoolExecutor INSTANT_POOL = new ThreadPoolExecutor(Config.INSTANT_THREAD_POOL_COUNT, Config.INSTANT_THREAD_POOL_COUNT, 0, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(100000));
public static void init()
{
// Feed scheduled pool.
for (int i = 0; i < Config.SCHEDULED_THREAD_POOL_COUNT; i++)
{
SCHEDULED_POOLS[i] = new ScheduledThreadPoolExecutor(Config.THREADS_PER_SCHEDULED_THREAD_POOL);
}
// Feed instant pool.
for (int i = 0; i < Config.INSTANT_THREAD_POOL_COUNT; i++)
{
INSTANT_POOLS[i] = new ThreadPoolExecutor(Config.THREADS_PER_INSTANT_THREAD_POOL, Config.THREADS_PER_INSTANT_THREAD_POOL, 0, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(100000));
}
// Prestart core threads.
for (ScheduledThreadPoolExecutor threadPool : SCHEDULED_POOLS)
{
threadPool.setRejectedExecutionHandler(new RejectedExecutionHandlerImpl());
threadPool.setRemoveOnCancelPolicy(true);
threadPool.prestartAllCoreThreads();
}
for (ThreadPoolExecutor threadPool : INSTANT_POOLS)
{
threadPool.setRejectedExecutionHandler(new RejectedExecutionHandlerImpl());
threadPool.prestartAllCoreThreads();
}
// Set pool options.
SCHEDULED_POOL.setRejectedExecutionHandler(new RejectedExecutionHandlerImpl());
SCHEDULED_POOL.setRemoveOnCancelPolicy(true);
SCHEDULED_POOL.prestartAllCoreThreads();
INSTANT_POOL.setRejectedExecutionHandler(new RejectedExecutionHandlerImpl());
INSTANT_POOL.prestartAllCoreThreads();
// Launch purge task.
scheduleAtFixedRate(() ->
{
purge();
}, 600000, 600000);
}, 60000, 60000);
LOGGER.info("ThreadPool: Initialized");
LOGGER.info("..." + Config.SCHEDULED_THREAD_POOL_COUNT + " scheduled pool executors with " + (Config.SCHEDULED_THREAD_POOL_COUNT * Config.THREADS_PER_SCHEDULED_THREAD_POOL) + " total threads.");
LOGGER.info("..." + Config.INSTANT_THREAD_POOL_COUNT + " instant pool executors with " + (Config.INSTANT_THREAD_POOL_COUNT * Config.THREADS_PER_INSTANT_THREAD_POOL) + " total threads.");
LOGGER.info("...scheduled pool executor with " + Config.SCHEDULED_THREAD_POOL_COUNT + " total threads.");
LOGGER.info("...instant pool executor with " + Config.INSTANT_THREAD_POOL_COUNT + " total threads.");
}
public static void purge()
{
for (ScheduledThreadPoolExecutor threadPool : SCHEDULED_POOLS)
{
threadPool.purge();
}
for (ThreadPoolExecutor threadPool : INSTANT_POOLS)
{
threadPool.purge();
}
SCHEDULED_POOL.purge();
INSTANT_POOL.purge();
}
/**
@ -102,16 +75,14 @@ public final class ThreadPool
*/
public static ScheduledFuture<?> schedule(Runnable runnable, long delay)
{
synchronized (SCHEDULED_POOLS)
try
{
try
{
return SCHEDULED_POOLS[SCHEDULED_THREAD_RANDOMIZER++ % Config.SCHEDULED_THREAD_POOL_COUNT].schedule(new RunnableWrapper(runnable), delay, TimeUnit.MILLISECONDS);
}
catch (Exception e)
{
return null;
}
return SCHEDULED_POOL.schedule(new RunnableWrapper(runnable), delay, TimeUnit.MILLISECONDS);
}
catch (Exception e)
{
LOGGER.warning(e.getMessage() + Config.EOL + e.getStackTrace());
return null;
}
}
@ -124,16 +95,14 @@ public final class ThreadPool
*/
public static ScheduledFuture<?> scheduleAtFixedRate(Runnable runnable, long initialDelay, long period)
{
synchronized (SCHEDULED_POOLS)
try
{
try
{
return SCHEDULED_POOLS[SCHEDULED_THREAD_RANDOMIZER++ % Config.SCHEDULED_THREAD_POOL_COUNT].scheduleAtFixedRate(new RunnableWrapper(runnable), initialDelay, period, TimeUnit.MILLISECONDS);
}
catch (Exception e)
{
return null;
}
return SCHEDULED_POOL.scheduleAtFixedRate(new RunnableWrapper(runnable), initialDelay, period, TimeUnit.MILLISECONDS);
}
catch (Exception e)
{
LOGGER.warning(e.getMessage() + Config.EOL + e.getStackTrace());
return null;
}
}
@ -143,50 +112,43 @@ public final class ThreadPool
*/
public static void execute(Runnable runnable)
{
synchronized (INSTANT_POOLS)
try
{
try
{
INSTANT_POOLS[INSTANT_THREAD_RANDOMIZER++ % Config.INSTANT_THREAD_POOL_COUNT].execute(new RunnableWrapper(runnable));
}
catch (Exception e)
{
}
INSTANT_POOL.execute(new RunnableWrapper(runnable));
}
catch (Exception e)
{
LOGGER.warning(e.getMessage() + Config.EOL + e.getStackTrace());
}
}
public static String[] getStats()
{
final String[] stats = new String[(SCHEDULED_POOLS.length + INSTANT_POOLS.length) * 10];
final String[] stats = new String[20];
int pos = 0;
for (int i = 0; i < SCHEDULED_POOLS.length; i++)
{
final ScheduledThreadPoolExecutor threadPool = SCHEDULED_POOLS[i];
stats[pos++] = "Scheduled pool #" + i + ":";
stats[pos++] = " |- ActiveCount: ...... " + threadPool.getActiveCount();
stats[pos++] = " |- CorePoolSize: ..... " + threadPool.getCorePoolSize();
stats[pos++] = " |- PoolSize: ......... " + threadPool.getPoolSize();
stats[pos++] = " |- LargestPoolSize: .. " + threadPool.getLargestPoolSize();
stats[pos++] = " |- MaximumPoolSize: .. " + threadPool.getMaximumPoolSize();
stats[pos++] = " |- CompletedTaskCount: " + threadPool.getCompletedTaskCount();
stats[pos++] = " |- QueuedTaskCount: .. " + threadPool.getQueue().size();
stats[pos++] = " |- TaskCount: ........ " + threadPool.getTaskCount();
stats[pos++] = " | -------";
}
for (int i = 0; i < INSTANT_POOLS.length; i++)
{
final ThreadPoolExecutor threadPool = INSTANT_POOLS[i];
stats[pos++] = "Instant pool #" + i + ":";
stats[pos++] = " |- ActiveCount: ...... " + threadPool.getActiveCount();
stats[pos++] = " |- CorePoolSize: ..... " + threadPool.getCorePoolSize();
stats[pos++] = " |- PoolSize: ......... " + threadPool.getPoolSize();
stats[pos++] = " |- LargestPoolSize: .. " + threadPool.getLargestPoolSize();
stats[pos++] = " |- MaximumPoolSize: .. " + threadPool.getMaximumPoolSize();
stats[pos++] = " |- CompletedTaskCount: " + threadPool.getCompletedTaskCount();
stats[pos++] = " |- QueuedTaskCount: .. " + threadPool.getQueue().size();
stats[pos++] = " |- TaskCount: ........ " + threadPool.getTaskCount();
stats[pos++] = " | -------";
}
stats[pos++] = "Scheduled pool:";
stats[pos++] = " |- ActiveCount: ...... " + SCHEDULED_POOL.getActiveCount();
stats[pos++] = " |- CorePoolSize: ..... " + SCHEDULED_POOL.getCorePoolSize();
stats[pos++] = " |- PoolSize: ......... " + SCHEDULED_POOL.getPoolSize();
stats[pos++] = " |- LargestPoolSize: .. " + SCHEDULED_POOL.getLargestPoolSize();
stats[pos++] = " |- MaximumPoolSize: .. " + SCHEDULED_POOL.getMaximumPoolSize();
stats[pos++] = " |- CompletedTaskCount: " + SCHEDULED_POOL.getCompletedTaskCount();
stats[pos++] = " |- QueuedTaskCount: .. " + SCHEDULED_POOL.getQueue().size();
stats[pos++] = " |- TaskCount: ........ " + SCHEDULED_POOL.getTaskCount();
stats[pos++] = " | -------";
stats[pos++] = "Instant pool:";
stats[pos++] = " |- ActiveCount: ...... " + INSTANT_POOL.getActiveCount();
stats[pos++] = " |- CorePoolSize: ..... " + INSTANT_POOL.getCorePoolSize();
stats[pos++] = " |- PoolSize: ......... " + INSTANT_POOL.getPoolSize();
stats[pos++] = " |- LargestPoolSize: .. " + INSTANT_POOL.getLargestPoolSize();
stats[pos++] = " |- MaximumPoolSize: .. " + INSTANT_POOL.getMaximumPoolSize();
stats[pos++] = " |- CompletedTaskCount: " + INSTANT_POOL.getCompletedTaskCount();
stats[pos++] = " |- QueuedTaskCount: .. " + INSTANT_POOL.getQueue().size();
stats[pos++] = " |- TaskCount: ........ " + INSTANT_POOL.getTaskCount();
stats[pos++] = " | -------";
return stats;
}
@ -198,14 +160,8 @@ public final class ThreadPool
try
{
LOGGER.info("ThreadPool: Shutting down.");
for (ScheduledThreadPoolExecutor threadPool : SCHEDULED_POOLS)
{
threadPool.shutdownNow();
}
for (ThreadPoolExecutor threadPool : INSTANT_POOLS)
{
threadPool.shutdownNow();
}
SCHEDULED_POOL.shutdownNow();
INSTANT_POOL.shutdownNow();
}
catch (Throwable t)
{