ThreadPool revert and path change.

This commit is contained in:
MobiusDevelopment
2021-10-27 00:58:25 +00:00
parent 4e9f507f33
commit a0ee3599f5
3743 changed files with 11356 additions and 9800 deletions

View File

@@ -71,7 +71,9 @@ public class Config
public static List<Integer> KARMA_PROTECTED_ITEMS;
// ThreadPool
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;
// Npc
public static boolean SHOW_NPC_LEVEL;
public static boolean SHOW_NPC_AGGRESSION;
@@ -119,8 +121,18 @@ public class Config
// Load threadpool config file (if exists)
final PropertiesParser threadpoolSettings = new PropertiesParser(THREADPOOL_CONFIG_FILE);
SCHEDULED_THREAD_POOL_COUNT = threadpoolSettings.getInt("ScheduledThreadPoolCount", 40);
INSTANT_THREAD_POOL_COUNT = threadpoolSettings.getInt("InstantThreadPoolCount", 20);
SCHEDULED_THREAD_POOL_COUNT = threadpoolSettings.getInt("ScheduledThreadPoolCount", -1);
if (SCHEDULED_THREAD_POOL_COUNT == -1)
{
SCHEDULED_THREAD_POOL_COUNT = Runtime.getRuntime().availableProcessors();
}
THREADS_PER_SCHEDULED_THREAD_POOL = threadpoolSettings.getInt("ThreadsPerScheduledThreadPool", 4);
INSTANT_THREAD_POOL_COUNT = threadpoolSettings.getInt("InstantThreadPoolCount", -1);
if (INSTANT_THREAD_POOL_COUNT == -1)
{
INSTANT_THREAD_POOL_COUNT = Runtime.getRuntime().availableProcessors();
}
THREADS_PER_INSTANT_THREAD_POOL = threadpoolSettings.getInt("ThreadsPerInstantThreadPool", 2);
// Load NPC config file (if exists)
final PropertiesParser npcSettings = new PropertiesParser(NPC_CONFIG_FILE);

View File

@@ -52,7 +52,7 @@ import org.l2jmobius.gameserver.handler.skillhandlers.HealSkill;
import org.l2jmobius.gameserver.managers.GmListManager;
import org.l2jmobius.gameserver.model.World;
import org.l2jmobius.gameserver.network.ClientThread;
import org.l2jmobius.gameserver.threadpool.ThreadPool;
import org.l2jmobius.gameserver.threads.ThreadPool;
import org.l2jmobius.loginserver.LoginController;
public class GameServer extends Thread

View File

@@ -31,7 +31,7 @@ import org.l2jmobius.gameserver.network.serverpackets.NpcInfo;
import org.l2jmobius.gameserver.network.serverpackets.PetInfo;
import org.l2jmobius.gameserver.network.serverpackets.PetItemList;
import org.l2jmobius.gameserver.templates.Npc;
import org.l2jmobius.gameserver.threadpool.ThreadPool;
import org.l2jmobius.gameserver.threads.ThreadPool;
public class PetSummon implements IItemHandler
{

View File

@@ -25,7 +25,7 @@ import org.l2jmobius.gameserver.model.actor.instance.ItemInstance;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.network.serverpackets.MagicSkillUser;
import org.l2jmobius.gameserver.network.serverpackets.SetupGauge;
import org.l2jmobius.gameserver.threadpool.ThreadPool;
import org.l2jmobius.gameserver.threads.ThreadPool;
public class ScrollOfEscape implements IItemHandler
{

View File

@@ -20,7 +20,7 @@ package org.l2jmobius.gameserver.model;
import java.util.concurrent.ScheduledFuture;
import org.l2jmobius.gameserver.model.actor.Creature;
import org.l2jmobius.gameserver.threadpool.ThreadPool;
import org.l2jmobius.gameserver.threads.ThreadPool;
public class Potion extends WorldObject
{

View File

@@ -24,7 +24,7 @@ import org.l2jmobius.gameserver.IdManager;
import org.l2jmobius.gameserver.model.actor.instance.MonsterInstance;
import org.l2jmobius.gameserver.model.actor.instance.NpcInstance;
import org.l2jmobius.gameserver.templates.Npc;
import org.l2jmobius.gameserver.threadpool.ThreadPool;
import org.l2jmobius.gameserver.threads.ThreadPool;
import org.l2jmobius.util.Rnd;
public class Spawn

View File

@@ -36,7 +36,7 @@ import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.network.serverpackets.DropItem;
import org.l2jmobius.gameserver.templates.Npc;
import org.l2jmobius.gameserver.templates.Weapon;
import org.l2jmobius.gameserver.threadpool.ThreadPool;
import org.l2jmobius.gameserver.threads.ThreadPool;
import org.l2jmobius.util.Rnd;
public class Attackable extends NpcInstance

View File

@@ -46,7 +46,7 @@ import org.l2jmobius.gameserver.network.serverpackets.StopMove;
import org.l2jmobius.gameserver.network.serverpackets.SystemMessage;
import org.l2jmobius.gameserver.network.serverpackets.TeleportToLocation;
import org.l2jmobius.gameserver.templates.Weapon;
import org.l2jmobius.gameserver.threadpool.ThreadPool;
import org.l2jmobius.gameserver.threads.ThreadPool;
import org.l2jmobius.util.Chronos;
import org.l2jmobius.util.Rnd;

View File

@@ -37,7 +37,7 @@ import org.l2jmobius.gameserver.network.serverpackets.SetToLocation;
import org.l2jmobius.gameserver.network.serverpackets.StatusUpdate;
import org.l2jmobius.gameserver.templates.Npc;
import org.l2jmobius.gameserver.templates.Weapon;
import org.l2jmobius.gameserver.threadpool.ThreadPool;
import org.l2jmobius.gameserver.threads.ThreadPool;
public class NpcInstance extends Creature
{

View File

@@ -47,7 +47,7 @@ import org.l2jmobius.gameserver.network.serverpackets.SystemMessage;
import org.l2jmobius.gameserver.network.serverpackets.UserInfo;
import org.l2jmobius.gameserver.templates.Npc;
import org.l2jmobius.gameserver.templates.Weapon;
import org.l2jmobius.gameserver.threadpool.ThreadPool;
import org.l2jmobius.gameserver.threads.ThreadPool;
public class PetInstance extends Creature
{

View File

@@ -80,7 +80,7 @@ import org.l2jmobius.gameserver.templates.Armor;
import org.l2jmobius.gameserver.templates.CharTemplate;
import org.l2jmobius.gameserver.templates.Item;
import org.l2jmobius.gameserver.templates.Weapon;
import org.l2jmobius.gameserver.threadpool.ThreadPool;
import org.l2jmobius.gameserver.threads.ThreadPool;
import org.l2jmobius.util.Chronos;
import org.l2jmobius.util.Rnd;

View File

@@ -1,169 +0,0 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.l2jmobius.gameserver.threadpool;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
import org.l2jmobius.Config;
/**
* 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>
* </ul>
*/
public class ThreadPool
{
private static final Logger LOGGER = Logger.getLogger(ThreadPool.class.getName());
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()
{
// 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(ThreadPool::purge, 60000, 60000);
LOGGER.info("ThreadPool: Initialized");
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()
{
SCHEDULED_POOL.purge();
INSTANT_POOL.purge();
}
/**
* Creates and executes a one-shot action that becomes enabled after the given delay.
* @param runnable : the task to execute.
* @param delay : the time from now to delay execution.
* @return a ScheduledFuture representing pending completion of the task and whose get() method will return null upon completion.
*/
public static ScheduledFuture<?> schedule(Runnable runnable, long delay)
{
try
{
return SCHEDULED_POOL.schedule(new RunnableWrapper(runnable), delay, TimeUnit.MILLISECONDS);
}
catch (Exception e)
{
LOGGER.warning(e.getMessage() + Config.EOL + e.getStackTrace());
return null;
}
}
/**
* Creates and executes a periodic action that becomes enabled first after the given initial delay.
* @param runnable : the task to execute.
* @param initialDelay : the time to delay first execution.
* @param period : the period between successive executions.
* @return a ScheduledFuture representing pending completion of the task, and whose get() method will throw an exception upon cancellation.
*/
public static ScheduledFuture<?> scheduleAtFixedRate(Runnable runnable, long initialDelay, long period)
{
try
{
return SCHEDULED_POOL.scheduleAtFixedRate(new RunnableWrapper(runnable), initialDelay, period, TimeUnit.MILLISECONDS);
}
catch (Exception e)
{
LOGGER.warning(e.getMessage() + Config.EOL + e.getStackTrace());
return null;
}
}
/**
* Executes the given task sometime in the future.
* @param runnable : the task to execute.
*/
public static void execute(Runnable runnable)
{
try
{
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[20];
int pos = 0;
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;
}
/**
* Shutdown thread pooling system correctly. Send different informations.
*/
public static void shutdown()
{
try
{
LOGGER.info("ThreadPool: Shutting down.");
SCHEDULED_POOL.shutdownNow();
INSTANT_POOL.shutdownNow();
}
catch (Throwable t)
{
LOGGER.info("ThreadPool: Problem at Shutting down. " + t.getMessage());
}
}
}

View File

@@ -15,13 +15,15 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.l2jmobius.gameserver.threadpool;
package org.l2jmobius.gameserver.threads;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.logging.Logger;
import org.l2jmobius.Config;
/**
* @author NB4L1
*/
@@ -30,22 +32,22 @@ public class RejectedExecutionHandlerImpl implements RejectedExecutionHandler
private static final Logger LOGGER = Logger.getLogger(RejectedExecutionHandlerImpl.class.getName());
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor)
public void rejectedExecution(Runnable runnable, ThreadPoolExecutor executor)
{
if (executor.isShutdown())
{
return;
}
LOGGER.warning(r + " from " + executor + " " + new RejectedExecutionException());
LOGGER.warning(runnable.getClass().getSimpleName() + Config.EOL + runnable + " from " + executor + " " + new RejectedExecutionException());
if (Thread.currentThread().getPriority() > Thread.NORM_PRIORITY)
{
new Thread(r).start();
new Thread(runnable).start();
}
else
{
r.run();
runnable.run();
}
}
}

View File

@@ -15,13 +15,10 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.l2jmobius.gameserver.threadpool;
package org.l2jmobius.gameserver.threads;
import java.lang.Thread.UncaughtExceptionHandler;
/**
* @author Mobius
*/
public class RunnableWrapper implements Runnable
{
private final Runnable _runnable;

View File

@@ -0,0 +1,215 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.l2jmobius.gameserver.threads;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
import org.l2jmobius.Config;
/**
* This class handles thread pooling system.<br>
* It relies on two ThreadPoolExecutor arrays, 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>
* </ul>
*/
public class ThreadPool
{
private static final Logger LOGGER = Logger.getLogger(ThreadPool.class.getName());
private static final ScheduledThreadPoolExecutor[] SCHEDULED_POOLS = new ScheduledThreadPoolExecutor[Config.SCHEDULED_THREAD_POOL_COUNT];
private static final ThreadPoolExecutor[] INSTANT_POOLS = new ThreadPoolExecutor[Config.INSTANT_THREAD_POOL_COUNT];
private static int SCHEDULED_THREAD_RANDOMIZER = 0;
private static int INSTANT_THREAD_RANDOMIZER = 0;
public static void init()
{
LOGGER.info("ThreadPool: Initialized");
// 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);
}
LOGGER.info("..." + Config.SCHEDULED_THREAD_POOL_COUNT + " scheduled pool executors with " + (Config.SCHEDULED_THREAD_POOL_COUNT * Config.THREADS_PER_SCHEDULED_THREAD_POOL) + " total threads.");
// 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<>(100000));
}
LOGGER.info("..." + Config.INSTANT_THREAD_POOL_COUNT + " instant pool executors with " + (Config.INSTANT_THREAD_POOL_COUNT * Config.THREADS_PER_INSTANT_THREAD_POOL) + " total threads.");
// 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();
}
// Launch purge task.
scheduleAtFixedRate(ThreadPool::purge, 60000, 60000);
}
public static void purge()
{
for (ScheduledThreadPoolExecutor threadPool : SCHEDULED_POOLS)
{
threadPool.purge();
}
for (ThreadPoolExecutor threadPool : INSTANT_POOLS)
{
threadPool.purge();
}
}
/**
* Creates and executes a one-shot action that becomes enabled after the given delay.
* @param runnable : the task to execute.
* @param delay : the time from now to delay execution.
* @return a ScheduledFuture representing pending completion of the task and whose get() method will return null upon completion.
*/
public static ScheduledFuture<?> schedule(Runnable runnable, long delay)
{
try
{
return SCHEDULED_POOLS[SCHEDULED_THREAD_RANDOMIZER++ % Config.SCHEDULED_THREAD_POOL_COUNT].schedule(new RunnableWrapper(runnable), delay, TimeUnit.MILLISECONDS);
}
catch (Exception e)
{
LOGGER.warning(e.getMessage() + Config.EOL + e.getStackTrace());
return null;
}
}
/**
* Creates and executes a periodic action that becomes enabled first after the given initial delay.
* @param runnable : the task to execute.
* @param initialDelay : the time to delay first execution.
* @param period : the period between successive executions.
* @return a ScheduledFuture representing pending completion of the task and whose get() method will throw an exception upon cancellation.
*/
public static ScheduledFuture<?> scheduleAtFixedRate(Runnable runnable, long initialDelay, long period)
{
try
{
return SCHEDULED_POOLS[SCHEDULED_THREAD_RANDOMIZER++ % Config.SCHEDULED_THREAD_POOL_COUNT].scheduleAtFixedRate(new RunnableWrapper(runnable), initialDelay, period, TimeUnit.MILLISECONDS);
}
catch (Exception e)
{
LOGGER.warning(e.getMessage() + Config.EOL + e.getStackTrace());
return null;
}
}
/**
* Executes the given task sometime in the future.
* @param runnable : the task to execute.
*/
public static void execute(Runnable runnable)
{
try
{
INSTANT_POOLS[INSTANT_THREAD_RANDOMIZER++ % Config.INSTANT_THREAD_POOL_COUNT].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];
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++] = " | -------";
}
return stats;
}
/**
* Shutdown thread pooling system correctly. Send different informations.
*/
public static void shutdown()
{
try
{
LOGGER.info("ThreadPool: Shutting down.");
for (ScheduledThreadPoolExecutor threadPool : SCHEDULED_POOLS)
{
threadPool.shutdownNow();
}
for (ThreadPoolExecutor threadPool : INSTANT_POOLS)
{
threadPool.shutdownNow();
}
}
catch (Throwable t)
{
LOGGER.info("ThreadPool: Problem at Shutting down. " + t.getMessage());
}
}
}