From b9f9638f4cde9505875e6f5b0a294f88965ea6cb Mon Sep 17 00:00:00 2001 From: MobiusDevelopment <8391001+MobiusDevelopment@users.noreply.github.com> Date: Sun, 24 Nov 2019 11:36:26 +0000 Subject: [PATCH] Addition of ThreadPool. --- .../dist/config/threadpool.ini | 11 + .../java/org/l2jmobius/Config.java | 10 + .../org/l2jmobius/gameserver/GameServer.java | 3 + .../handler/itemhandlers/PetSummon.java | 24 +- .../handler/itemhandlers/ScrollOfEscape.java | 31 ++- .../l2jmobius/gameserver/model/Potion.java | 92 +++----- .../org/l2jmobius/gameserver/model/Spawn.java | 18 +- .../gameserver/model/actor/Attackable.java | 75 +++--- .../gameserver/model/actor/Creature.java | 204 ++++++----------- .../model/actor/instance/NpcInstance.java | 28 +-- .../model/actor/instance/PetInstance.java | 11 +- .../model/actor/instance/PlayerInstance.java | 216 ++++++++---------- .../RejectedExecutionHandlerImpl.java | 51 +++++ .../threadpool/RunnableWrapper.java | 51 +++++ .../gameserver/threadpool/ThreadPool.java | 172 ++++++++++++++ 15 files changed, 571 insertions(+), 426 deletions(-) create mode 100644 L2J_Mobius_C1_HarbingersOfWar/dist/config/threadpool.ini create mode 100644 L2J_Mobius_C1_HarbingersOfWar/java/org/l2jmobius/gameserver/threadpool/RejectedExecutionHandlerImpl.java create mode 100644 L2J_Mobius_C1_HarbingersOfWar/java/org/l2jmobius/gameserver/threadpool/RunnableWrapper.java create mode 100644 L2J_Mobius_C1_HarbingersOfWar/java/org/l2jmobius/gameserver/threadpool/ThreadPool.java diff --git a/L2J_Mobius_C1_HarbingersOfWar/dist/config/threadpool.ini b/L2J_Mobius_C1_HarbingersOfWar/dist/config/threadpool.ini new file mode 100644 index 0000000000..04082554a3 --- /dev/null +++ b/L2J_Mobius_C1_HarbingersOfWar/dist/config/threadpool.ini @@ -0,0 +1,11 @@ +# --------------------------------------------------------------------------- +# Threadpool Settings +# --------------------------------------------------------------------------- + +# Specifies how many threads will be in the scheduled pool. +# Default: 40 +ScheduledThreadPoolCount = 40 + +# Specifies how many threads will be in the single instant pool. +# Default: 20 +InstantThreadPoolCount = 20 \ No newline at end of file diff --git a/L2J_Mobius_C1_HarbingersOfWar/java/org/l2jmobius/Config.java b/L2J_Mobius_C1_HarbingersOfWar/java/org/l2jmobius/Config.java index a9fa9da78d..395f88b791 100644 --- a/L2J_Mobius_C1_HarbingersOfWar/java/org/l2jmobius/Config.java +++ b/L2J_Mobius_C1_HarbingersOfWar/java/org/l2jmobius/Config.java @@ -39,6 +39,7 @@ public class Config private static final String SERVER_CONFIG_FILE = "config/server.ini"; private static final String RATES_CONFIG_FILE = "config/rates.ini"; private static final String KARMA_CONFIG_FILE = "config/karma.ini"; + private static final String THREADPOOL_CONFIG_FILE = "config/threadpool.ini"; // Game public static String _ip; @@ -64,6 +65,9 @@ public class Config public static float KARMA_LOST_MULTIPLIER; public static int KARMA_DROP_CHANCE; public static List KARMA_PROTECTED_ITEMS; + // ThreadPool + public static int SCHEDULED_THREAD_POOL_COUNT; + public static int INSTANT_THREAD_POOL_COUNT; public static void load() { @@ -107,5 +111,11 @@ public class Config KARMA_LOST_MULTIPLIER = karmaSettings.getFloat("KarmaLostMultiplier", 1); KARMA_DROP_CHANCE = karmaSettings.getInt("KarmaDropChance", 5); KARMA_PROTECTED_ITEMS = Arrays.stream(karmaSettings.getIntArray("KarmaProtectedItems", ";")).boxed().collect(Collectors.toList()); + + // 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); } } diff --git a/L2J_Mobius_C1_HarbingersOfWar/java/org/l2jmobius/gameserver/GameServer.java b/L2J_Mobius_C1_HarbingersOfWar/java/org/l2jmobius/gameserver/GameServer.java index 7acdae51d6..cbe87744a4 100644 --- a/L2J_Mobius_C1_HarbingersOfWar/java/org/l2jmobius/gameserver/GameServer.java +++ b/L2J_Mobius_C1_HarbingersOfWar/java/org/l2jmobius/gameserver/GameServer.java @@ -52,6 +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.loginserver.LoginController; public class GameServer extends Thread @@ -124,6 +125,8 @@ public class GameServer extends Thread { super("GameServer"); + ThreadPool.init(); + if (!Config.SERVER_HOST_NAME.equals("*")) { final InetAddress adr = InetAddress.getByName(Config.SERVER_HOST_NAME); diff --git a/L2J_Mobius_C1_HarbingersOfWar/java/org/l2jmobius/gameserver/handler/itemhandlers/PetSummon.java b/L2J_Mobius_C1_HarbingersOfWar/java/org/l2jmobius/gameserver/handler/itemhandlers/PetSummon.java index dfc969f758..76263a7e1d 100644 --- a/L2J_Mobius_C1_HarbingersOfWar/java/org/l2jmobius/gameserver/handler/itemhandlers/PetSummon.java +++ b/L2J_Mobius_C1_HarbingersOfWar/java/org/l2jmobius/gameserver/handler/itemhandlers/PetSummon.java @@ -31,6 +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; public class PetSummon implements IItemHandler { @@ -109,20 +110,17 @@ public class PetSummon implements IItemHandler activeChar.broadcastPacket(ni); activeChar.sendPacket(ownerni); activeChar.sendPacket(new PetItemList(newpet)); - try + + ThreadPool.schedule(() -> { - Thread.sleep(900L); - } - catch (InterruptedException e) - { - // empty catch block - } - activeChar.sendPacket(new MagicSkillLaunched(activeChar, 2046, 1)); - activeChar.setPet(newpet); - newpet.setOwner(activeChar); - newpet.addKnownObject(activeChar); - newpet.setFollowStatus(true); - newpet.followOwner(activeChar); + activeChar.sendPacket(new MagicSkillLaunched(activeChar, 2046, 1)); + activeChar.setPet(newpet); + newpet.setOwner(activeChar); + newpet.addKnownObject(activeChar); + newpet.setFollowStatus(true); + newpet.followOwner(activeChar); + }, 900); + return 0; } diff --git a/L2J_Mobius_C1_HarbingersOfWar/java/org/l2jmobius/gameserver/handler/itemhandlers/ScrollOfEscape.java b/L2J_Mobius_C1_HarbingersOfWar/java/org/l2jmobius/gameserver/handler/itemhandlers/ScrollOfEscape.java index 6fe704a0db..b0e78f38e3 100644 --- a/L2J_Mobius_C1_HarbingersOfWar/java/org/l2jmobius/gameserver/handler/itemhandlers/ScrollOfEscape.java +++ b/L2J_Mobius_C1_HarbingersOfWar/java/org/l2jmobius/gameserver/handler/itemhandlers/ScrollOfEscape.java @@ -23,10 +23,9 @@ import org.l2jmobius.gameserver.handler.IItemHandler; import org.l2jmobius.gameserver.model.Skill; import org.l2jmobius.gameserver.model.actor.instance.ItemInstance; import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance; -import org.l2jmobius.gameserver.network.serverpackets.ActionFailed; import org.l2jmobius.gameserver.network.serverpackets.MagicSkillUser; import org.l2jmobius.gameserver.network.serverpackets.SetupGauge; -import org.l2jmobius.gameserver.network.serverpackets.StopMove; +import org.l2jmobius.gameserver.threadpool.ThreadPool; public class ScrollOfEscape implements IItemHandler { @@ -38,30 +37,28 @@ public class ScrollOfEscape implements IItemHandler @Override public int useItem(PlayerInstance activeChar, ItemInstance item) { - final int[] townCords = MapRegionTable.getInstance().getClosestTownCords(activeChar); + if (activeChar.isAllSkillsDisabled()) + { + return 0; + } + + activeChar.disableAllSkills(); activeChar.setTarget(activeChar); final Skill skill = SkillTable.getInstance().getInfo(1050, 1); final MagicSkillUser msk = new MagicSkillUser(activeChar, 1050, 1, 20000, 0); activeChar.sendPacket(msk); activeChar.broadcastPacket(msk); activeChar.sendPacket(new SetupGauge(SetupGauge.BLUE, skill.getSkillTime())); - if (skill.getSkillTime() > 200) + + ThreadPool.schedule(() -> { - try + if (activeChar.isAllSkillsDisabled()) { - Thread.sleep(skill.getSkillTime() - 200); + final int[] townCords = MapRegionTable.getInstance().getClosestTownCords(activeChar); + activeChar.teleToLocation(townCords[0], townCords[1], townCords[2]); + activeChar.enableAllSkills(); } - catch (InterruptedException e) - { - // empty catch block - } - } - final StopMove sm = new StopMove(activeChar); - activeChar.sendPacket(sm); - activeChar.broadcastPacket(sm); - final ActionFailed af = new ActionFailed(); - activeChar.sendPacket(af); - activeChar.teleToLocation(townCords[0], townCords[1], townCords[2]); + }, skill.getSkillTime() > 200 ? skill.getSkillTime() - 200 : 0); return 1; } diff --git a/L2J_Mobius_C1_HarbingersOfWar/java/org/l2jmobius/gameserver/model/Potion.java b/L2J_Mobius_C1_HarbingersOfWar/java/org/l2jmobius/gameserver/model/Potion.java index 0b8d32a79f..1ede9069ce 100644 --- a/L2J_Mobius_C1_HarbingersOfWar/java/org/l2jmobius/gameserver/model/Potion.java +++ b/L2J_Mobius_C1_HarbingersOfWar/java/org/l2jmobius/gameserver/model/Potion.java @@ -17,21 +17,16 @@ */ package org.l2jmobius.gameserver.model; -import java.util.Timer; -import java.util.TimerTask; -import java.util.logging.Logger; +import java.util.concurrent.ScheduledFuture; import org.l2jmobius.gameserver.model.actor.Creature; +import org.l2jmobius.gameserver.threadpool.ThreadPool; public class Potion extends WorldObject { - private static final Logger _log = Logger.getLogger(Potion.class.getName()); Creature _target; - private static Timer _regenTimer = new Timer(true); - private PotionHpHealing _potionhpRegTask; - // private boolean _potionhpRegenActive; - private PotionMpHealing _potionmpRegTask; - // private boolean _potionmpRegenActive; + private ScheduledFuture _potionhpRegTask; + private ScheduledFuture _potionmpRegTask; private int _seconds; private double _effect; private int _duration; @@ -41,27 +36,22 @@ public class Potion extends WorldObject public Potion() { - _potionhpRegTask = new PotionHpHealing(_target); - _potionmpRegTask = new PotionMpHealing(_target); _mpLock = new Object(); _hpLock = new Object(); } private void startPotionHpRegeneration(Creature activeChar) { - _potionhpRegTask = new PotionHpHealing(activeChar); - _regenTimer.schedule(_potionhpRegTask, 1000L, _seconds); - // this._potionhpRegenActive = true; + _potionhpRegTask = ThreadPool.scheduleAtFixedRate(new PotionHpHealing(activeChar), 1000, _seconds); } public void stopPotionHpRegeneration() { if (_potionhpRegTask != null) { - _potionhpRegTask.cancel(); + _potionhpRegTask.cancel(true); } _potionhpRegTask = null; - // this._potionhpRegenActive = false; } public void setCurrentHpPotion2(Creature activeChar) @@ -149,19 +139,16 @@ public class Potion extends WorldObject private void startPotionMpRegeneration(Creature activeChar) { - _potionmpRegTask = new PotionMpHealing(activeChar); - _regenTimer.schedule(_potionmpRegTask, 1000L, _seconds); - // this._potionmpRegenActive = true; + _potionmpRegTask = ThreadPool.scheduleAtFixedRate(new PotionMpHealing(activeChar), 1000, _seconds); } public void stopPotionMpRegeneration() { if (_potionmpRegTask != null) { - _potionmpRegTask.cancel(); + _potionmpRegTask.cancel(true); } _potionmpRegTask = null; - // this._potionmpRegenActive = false; } public void setCurrentMpPotion2(Creature activeChar) @@ -199,7 +186,7 @@ public class Potion extends WorldObject } } - class PotionMpHealing extends TimerTask + class PotionMpHealing implements Runnable { Creature _instance; @@ -211,32 +198,25 @@ public class Potion extends WorldObject @Override public void run() { - try + final Object object = _mpLock; + synchronized (object) { - final Object object = _mpLock; - synchronized (object) + double nowMp = _instance.getCurrentMp(); + if (_duration == 0) { - double nowMp = _instance.getCurrentMp(); - if (_duration == 0) - { - stopPotionMpRegeneration(); - } - if (_duration != 0) - { - _instance.setCurrentMp(nowMp += _effect); - _duration = _duration - (_seconds / 1000); - setCurrentMpPotion2(_instance); - } + stopPotionMpRegeneration(); + } + if (_duration != 0) + { + _instance.setCurrentMp(nowMp += _effect); + _duration = _duration - (_seconds / 1000); + setCurrentMpPotion2(_instance); } - } - catch (Exception e) - { - _log.warning("error in mp potion task:" + e); } } } - class PotionHpHealing extends TimerTask + class PotionHpHealing implements Runnable { Creature _instance; @@ -248,29 +228,21 @@ public class Potion extends WorldObject @Override public void run() { - try + final Object object = _hpLock; + synchronized (object) { - final Object object = _hpLock; - synchronized (object) + double nowHp = _instance.getCurrentHp(); + if (_duration == 0) { - double nowHp = _instance.getCurrentHp(); - if (_duration == 0) - { - stopPotionHpRegeneration(); - } - if (_duration != 0) - { - _instance.setCurrentHp(nowHp += _effect); - _duration = _duration - (_seconds / 1000); - setCurrentHpPotion2(_instance); - } + stopPotionHpRegeneration(); + } + if (_duration != 0) + { + _instance.setCurrentHp(nowHp += _effect); + _duration = _duration - (_seconds / 1000); + setCurrentHpPotion2(_instance); } - } - catch (Exception e) - { - _log.warning("Error in hp potion task:" + e); } } } - } diff --git a/L2J_Mobius_C1_HarbingersOfWar/java/org/l2jmobius/gameserver/model/Spawn.java b/L2J_Mobius_C1_HarbingersOfWar/java/org/l2jmobius/gameserver/model/Spawn.java index 78a2da3959..c1c442cde3 100644 --- a/L2J_Mobius_C1_HarbingersOfWar/java/org/l2jmobius/gameserver/model/Spawn.java +++ b/L2J_Mobius_C1_HarbingersOfWar/java/org/l2jmobius/gameserver/model/Spawn.java @@ -18,14 +18,13 @@ package org.l2jmobius.gameserver.model; import java.lang.reflect.Constructor; -import java.util.Timer; -import java.util.TimerTask; import java.util.logging.Logger; import org.l2jmobius.gameserver.IdFactory; 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.util.Rnd; public class Spawn @@ -45,7 +44,6 @@ public class Spawn private int _randomy; private int _heading; private int _respawnDelay; - private static Timer _spawnTimer = new Timer(true); private final Constructor _constructor; public Spawn(Npc mobTemplate) throws SecurityException, ClassNotFoundException @@ -161,8 +159,7 @@ public class Spawn if ((_scheduledCount + _currentCount) < _maximumCount) { ++_scheduledCount; - final SpawnTask task = new SpawnTask(npcId); - _spawnTimer.schedule(task, _respawnDelay); + ThreadPool.schedule(new SpawnTask(npcId), _respawnDelay); } } @@ -256,7 +253,7 @@ public class Spawn _respawnDelay = i * 1000; } - class SpawnTask extends TimerTask + class SpawnTask implements Runnable { NpcInstance _instance; int _objId; @@ -269,14 +266,7 @@ public class Spawn @Override public void run() { - try - { - doSpawn(); - } - catch (Exception e) - { - e.printStackTrace(); - } + doSpawn(); _scheduledCount--; } } diff --git a/L2J_Mobius_C1_HarbingersOfWar/java/org/l2jmobius/gameserver/model/actor/Attackable.java b/L2J_Mobius_C1_HarbingersOfWar/java/org/l2jmobius/gameserver/model/actor/Attackable.java index 0c8fadb7a5..d08ef4b912 100644 --- a/L2J_Mobius_C1_HarbingersOfWar/java/org/l2jmobius/gameserver/model/actor/Attackable.java +++ b/L2J_Mobius_C1_HarbingersOfWar/java/org/l2jmobius/gameserver/model/actor/Attackable.java @@ -21,9 +21,7 @@ import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.Timer; -import java.util.TimerTask; -import java.util.logging.Logger; +import java.util.concurrent.ScheduledFuture; import org.l2jmobius.Config; import org.l2jmobius.gameserver.data.ItemTable; @@ -38,18 +36,15 @@ 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.util.Rnd; public class Attackable extends NpcInstance { - private static Logger _log = Logger.getLogger(Attackable.class.getName()); - // private int _moveRadius; private boolean _active; - private AITask _currentAiTask; - private AIAttackeTask _currentAIAttackTask; - private static Timer _aiTimer = new Timer(true); - private static Timer _attackTimer = new Timer(true); + private ScheduledFuture _currentAiTask; + private ScheduledFuture _currentAIAttackTask; private final Map _aggroList = new HashMap<>(); private Weapon _dummyWeapon; private boolean _sweepActive; @@ -89,16 +84,14 @@ public class Attackable extends NpcInstance if (_active) { final int wait = (10 + Rnd.get(120)) * 1000; - _currentAiTask = new AITask(this); - _aiTimer.schedule(_currentAiTask, wait); + _currentAiTask = ThreadPool.schedule(new AITask(this), wait); } } protected void startRandomWalking() { - _currentAiTask = new AITask(this); final int wait = (10 + Rnd.get(120)) * 1000; - _aiTimer.schedule(_currentAiTask, wait); + _currentAiTask = ThreadPool.schedule(new AITask(this), wait); setCurrentState(CreatureState.RANDOM_WALK); } @@ -106,8 +99,7 @@ public class Attackable extends NpcInstance { if ((_currentAIAttackTask == null) && (getTarget() == null)) { - _currentAIAttackTask = new AIAttackeTask(this); - _attackTimer.scheduleAtFixedRate(_currentAIAttackTask, 100L, 1000L); + _currentAIAttackTask = ThreadPool.scheduleAtFixedRate(new AIAttackeTask(this), 100, 1000); } } @@ -320,7 +312,7 @@ public class Attackable extends NpcInstance { if (_currentAiTask != null) { - _currentAiTask.cancel(); + _currentAiTask.cancel(true); _currentAiTask = null; } } @@ -334,7 +326,7 @@ public class Attackable extends NpcInstance { if (_currentAIAttackTask != null) { - _currentAIAttackTask.cancel(); + _currentAIAttackTask.cancel(true); _currentAIAttackTask = null; } } @@ -401,7 +393,7 @@ public class Attackable extends NpcInstance _sweepActive = sweepActive; } - class AIAttackeTask extends TimerTask + class AIAttackeTask implements Runnable { Creature _instance; @@ -413,37 +405,30 @@ public class Attackable extends NpcInstance @Override public void run() { - try + if (!isInCombat()) { - if (!isInCombat()) + for (PlayerInstance player : getKnownPlayers()) { - for (PlayerInstance player : getKnownPlayers()) + if (!getCondition2(player) || !(getDistance(player.getX(), player.getY()) <= (getCollisionRadius() + 200.0))) { - if (!getCondition2(player) || !(getDistance(player.getX(), player.getY()) <= (getCollisionRadius() + 200.0))) - { - continue; - } - if (_currentAiTask != null) - { - _currentAiTask.cancel(); - } - setTarget(player); - startAttack(player); + continue; } - } - else if (_currentAIAttackTask != null) - { - _currentAIAttackTask.cancel(); + if (_currentAiTask != null) + { + _currentAiTask.cancel(true); + } + setTarget(player); + startAttack(player); } } - catch (Exception e) + else if (_currentAIAttackTask != null) { - _log.severe(e.toString()); + _currentAIAttackTask.cancel(true); } } } - class AITask extends TimerTask + class AITask implements Runnable { Creature _instance; @@ -455,17 +440,9 @@ public class Attackable extends NpcInstance @Override public void run() { - try - { - final int x1 = (getX() + Rnd.get(500)) - 250; - final int y1 = (getY() + Rnd.get(500)) - 250; - moveTo(x1, y1, getZ(), 0); - } - catch (Exception e) - { - _log.severe(e.toString()); - } + final int x1 = (getX() + Rnd.get(500)) - 250; + final int y1 = (getY() + Rnd.get(500)) - 250; + moveTo(x1, y1, getZ(), 0); } } - } diff --git a/L2J_Mobius_C1_HarbingersOfWar/java/org/l2jmobius/gameserver/model/actor/Creature.java b/L2J_Mobius_C1_HarbingersOfWar/java/org/l2jmobius/gameserver/model/actor/Creature.java index 4eca63b7da..8b09d37a4c 100644 --- a/L2J_Mobius_C1_HarbingersOfWar/java/org/l2jmobius/gameserver/model/actor/Creature.java +++ b/L2J_Mobius_C1_HarbingersOfWar/java/org/l2jmobius/gameserver/model/actor/Creature.java @@ -21,8 +21,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Set; -import java.util.Timer; -import java.util.TimerTask; +import java.util.concurrent.ScheduledFuture; import java.util.logging.Logger; import org.l2jmobius.gameserver.enums.CreatureState; @@ -47,6 +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.util.Rnd; public abstract class Creature extends WorldObject @@ -54,29 +54,20 @@ public abstract class Creature extends WorldObject private static final Logger _log = Logger.getLogger(Creature.class.getName()); public long serialVersionUID = 305402420L; private final List _statusListener = new ArrayList<>(); - private static Timer _attackTimer = new Timer(true); - private AttackTask _currentAttackTask; - private static Timer _hitTimer = new Timer(true); - private HitTask _currentHitTask; - private static Timer _regenTimer = new Timer(true); - private MpRegenTask _mpRegTask; + private ScheduledFuture _attackTask; + private ScheduledFuture _hitTask; + private ScheduledFuture _regenTask; private final Object _mpLock = new Object(); private boolean _mpRegenActive; - private HpRegenTask _hpRegTask = new HpRegenTask(this); private final Object _hpLock = new Object(); private boolean _hpRegenActive; - // private static Timer _bowAttack = new Timer(true); private int _moveOffset; private float _effectiveSpeed; - // private float _dx; - // private float _dy; - // private float _dz; private long _moveStartTime; private double _xAddition; private double _yAddition; private long _timeToTarget; - private static Timer _moveTimer = new Timer(true); - private ArriveTask _currentMoveTask; + private ScheduledFuture _moveTask; private String _name; private int _level = 1; private int _maxHp; @@ -246,10 +237,10 @@ public abstract class Creature extends WorldObject public void stopMove() { - if (_currentMoveTask != null) + if (_moveTask != null) { - _currentMoveTask.cancel(); - _currentMoveTask = null; + _moveTask.cancel(true); + _moveTask = null; } setX(getX()); setY(getY()); @@ -341,16 +332,18 @@ public abstract class Creature extends WorldObject { if (_hpRegenActive) { - _hpRegTask.cancel(); - _hpRegTask = null; + if (_regenTask != null) + { + _regenTask.cancel(true); + _regenTask = null; + } _hpRegenActive = false; } } private void startHpRegeneration() { - _hpRegTask = new HpRegenTask(this); - _regenTimer.scheduleAtFixedRate(_hpRegTask, 3000L, 3000L); + _regenTask = ThreadPool.scheduleAtFixedRate(new HpRegenTask(this), 3000, 3000); _hpRegenActive = true; } @@ -376,8 +369,7 @@ public abstract class Creature extends WorldObject private void startMpRegeneration() { - _mpRegTask = new MpRegenTask(this); - _regenTimer.scheduleAtFixedRate(_mpRegTask, 3000L, 3000L); + _regenTask = ThreadPool.scheduleAtFixedRate(new MpRegenTask(this), 3000, 3000); _mpRegenActive = true; } @@ -385,8 +377,8 @@ public abstract class Creature extends WorldObject { if (_mpRegenActive) { - _mpRegTask.cancel(); - _mpRegTask = null; + _regenTask.cancel(true); + _regenTask = null; _mpRegenActive = false; } } @@ -807,17 +799,17 @@ public abstract class Creature extends WorldObject _currentHp = 0.0; stopHpRegeneration(); stopMpRegeneration(); - if (_currentAttackTask != null) + if (_attackTask != null) { - _currentAttackTask.cancel(); + _attackTask.cancel(true); } - if (_currentHitTask != null) + if (_hitTask != null) { - _currentHitTask.cancel(); + _hitTask.cancel(true); } - if (_currentMoveTask != null) + if (_moveTask != null) { - _currentMoveTask.cancel(); + _moveTask.cancel(true); } broadcastStatusUpdate(); final StopMove stop = new StopMove(this); @@ -840,7 +832,7 @@ public abstract class Creature extends WorldObject { _moveOffset = offset; final double distance = getDistance(x, y); - if ((distance > 0.0) || (offset > 0)) + if ((distance > 0) || (offset > 0)) { if (offset == 0) { @@ -896,9 +888,7 @@ public abstract class Creature extends WorldObject } if ((getPawnTarget() != null) && (distance <= getAttackRange()) && (getCurrentState() == CreatureState.FOLLOW)) { - final ArriveTask newMoveTask = new ArriveTask(this); - _moveTimer.schedule(newMoveTask, 3000L); - _currentMoveTask = newMoveTask; + _moveTask = ThreadPool.schedule(new ArriveTask(this), 3000); return; } int dx = x - getX(); @@ -945,48 +935,46 @@ public abstract class Creature extends WorldObject { if (getCurrentState() == CreatureState.INTERACT) { - _moveTimer.schedule(newMoveTask, _timeToTarget); - _currentMoveTask = newMoveTask; + _moveTask = ThreadPool.schedule(newMoveTask, _timeToTarget); setIsMoving(true); return; } if ((_timeToTarget < 2000L) && (distance > getAttackRange())) { - _moveTimer.schedule(newMoveTask, _timeToTarget); + _moveTask = ThreadPool.schedule(newMoveTask, _timeToTarget); } else if (getPawnTarget().isMoving()) { - _moveTimer.schedule(newMoveTask, 2000L); + _moveTask = ThreadPool.schedule(newMoveTask, 2000); } else { - _moveTimer.schedule(newMoveTask, 3000L); + _moveTask = ThreadPool.schedule(newMoveTask, 3000); } } else { - _moveTimer.schedule(newMoveTask, _timeToTarget); + _moveTask = ThreadPool.schedule(newMoveTask, _timeToTarget); } - _currentMoveTask = newMoveTask; setIsMoving(true); } } protected void stopHitTask() { - if (_currentHitTask != null) + if (_hitTask != null) { - _currentHitTask.cancel(); - _currentHitTask = null; + _hitTask.cancel(true); + _hitTask = null; } } protected void stopAttackTask() { - if (_currentAttackTask != null) + if (_attackTask != null) { - _currentAttackTask.cancel(); - _currentAttackTask = null; + _attackTask.cancel(true); + _attackTask = null; } } @@ -1073,20 +1061,19 @@ public abstract class Creature extends WorldObject protected void startCombat() { - if (_currentAttackTask == null) + if (_attackTask == null) { - _currentAttackTask = new AttackTask(this); - _attackTimer.schedule(_currentAttackTask, 0L); - } - else - { - _log.warning("Multiple attacks want to start in parallel. Prevented."); + _attackTask = ThreadPool.schedule(new AttackTask(this), 0); } + // else + // { + // _log.warning("Multiple attacks want to start in parallel. Prevented."); + // } } private void onAttackTimer() { - _currentAttackTask = null; + _attackTask = null; final Creature target = (Creature) _attackTarget; if (isDead() || (target == null) || target.isDead() || ((getCurrentState() != CreatureState.ATTACKING) && (getCurrentState() != CreatureState.CASTING)) || !target.knownsObject(this) || !knownsObject(target)) { @@ -1166,8 +1153,8 @@ public abstract class Creature extends WorldObject } if (isUsingDualWeapon()) { - _hitTimer.schedule(new HitTask(this, target, damage, crit, miss, false), calculateHitSpeed(weaponItem, 1)); - _hitTimer.schedule(new HitTask(this, target, damage, crit, miss, false), calculateHitSpeed(weaponItem, 2)); + _hitTask = ThreadPool.schedule(new HitTask(this, target, damage, crit, miss, false), calculateHitSpeed(weaponItem, 1)); + _hitTask = ThreadPool.schedule(new HitTask(this, target, damage, crit, miss, false), calculateHitSpeed(weaponItem, 2)); } else if (getActiveWeapon().getWeaponType() == 5) { @@ -1183,11 +1170,11 @@ public abstract class Creature extends WorldObject reduceCurrentMp(weaponItem.getMpConsume()); sendPacket(new SystemMessage(SystemMessage.GETTING_READY_TO_SHOOT_AN_ARROW)); sendPacket(new SetupGauge(SetupGauge.RED, calculateAttackSpeed(weaponItem) * 2)); - _hitTimer.schedule(new HitTask(this, target, damage, crit, miss, false), calculateHitSpeed(weaponItem, 1)); + _hitTask = ThreadPool.schedule(new HitTask(this, target, damage, crit, miss, false), calculateHitSpeed(weaponItem, 1)); } else { - _hitTimer.schedule(new HitTask(this, target, damage, crit, miss, false), calculateHitSpeed(weaponItem, 1)); + _hitTask = ThreadPool.schedule(new HitTask(this, target, damage, crit, miss, false), calculateHitSpeed(weaponItem, 1)); } final Attack attack = new Attack(getObjectId(), _attackTarget.getObjectId(), damage, miss, crit, soulShotUse, getX(), getY(), getZ()); setActiveSoulshotGrade(0); @@ -1224,7 +1211,7 @@ public abstract class Creature extends WorldObject if (getActiveWeapon().getWeaponType() == 5) { reduceArrowCount(); - _attackTimer.schedule(new AttackTask(this), calculateAttackSpeed(getActiveWeapon())); + _attackTask = ThreadPool.schedule(new AttackTask(this), calculateAttackSpeed(getActiveWeapon())); } displayHitMessage(damage, crit, miss); if (!miss) @@ -1237,7 +1224,7 @@ public abstract class Creature extends WorldObject { _2ndHit = false; _currentlyAttacking = false; - _attackTimer.schedule(new AttackTask(this), calculateAttackSpeed(getActiveWeapon())); + _attackTask = ThreadPool.schedule(new AttackTask(this), calculateAttackSpeed(getActiveWeapon())); } else { @@ -1247,7 +1234,7 @@ public abstract class Creature extends WorldObject if (!isUsingDualWeapon()) { _currentlyAttacking = false; - _attackTimer.schedule(new AttackTask(this), calculateAttackSpeed(getActiveWeapon())); + _attackTask = ThreadPool.schedule(new AttackTask(this), calculateAttackSpeed(getActiveWeapon())); } } } @@ -1389,11 +1376,11 @@ public abstract class Creature extends WorldObject _currentlyAttacking = status; } - protected void enableAllSkills() + public void enableAllSkills() { } - public class DecayTask extends TimerTask + public class DecayTask implements Runnable { Creature _instance; @@ -1409,7 +1396,7 @@ public abstract class Creature extends WorldObject } } - class MpRegenTask extends TimerTask + class MpRegenTask implements Runnable { Creature _instance; @@ -1421,26 +1408,19 @@ public abstract class Creature extends WorldObject @Override public void run() { - try + final Object object = _mpLock; + synchronized (object) { - final Object object = _mpLock; - synchronized (object) + double nowMp = _instance.getCurrentMp(); + if (_instance.getCurrentMp() < _instance.getMaxMp()) { - double nowMp = _instance.getCurrentMp(); - if (_instance.getCurrentMp() < _instance.getMaxMp()) - { - _instance.setCurrentMp(nowMp += _instance.getMaxMp() * 0.014); - } + _instance.setCurrentMp(nowMp += _instance.getMaxMp() * 0.014); } } - catch (Exception e) - { - _log.severe(e.toString()); - } } } - class HpRegenTask extends TimerTask + class HpRegenTask implements Runnable { Creature _instance; @@ -1452,29 +1432,22 @@ public abstract class Creature extends WorldObject @Override public void run() { - try + synchronized (_hpLock) { - synchronized (_hpLock) + double nowHp = _instance.getCurrentHp(); + if (_instance.getCurrentHp() < _instance.getMaxHp()) { - double nowHp = _instance.getCurrentHp(); - if (_instance.getCurrentHp() < _instance.getMaxHp()) + if ((nowHp += _instance.getMaxHp() * 0.018) > _instance.getMaxHp()) { - if ((nowHp += _instance.getMaxHp() * 0.018) > _instance.getMaxHp()) - { - nowHp = _instance.getMaxHp(); - } - _instance.setCurrentHp(nowHp); + nowHp = _instance.getMaxHp(); } + _instance.setCurrentHp(nowHp); } } - catch (Exception e) - { - _log.severe(e.toString()); - } } } - class HitTask extends TimerTask + class HitTask implements Runnable { Creature _instance; Creature _target; @@ -1496,18 +1469,11 @@ public abstract class Creature extends WorldObject @Override public void run() { - try - { - _instance.onHitTimer(_target, _damage, _crit, _miss, _soulshot); - } - catch (Exception e) - { - _log.severe(e.toString()); - } + _instance.onHitTimer(_target, _damage, _crit, _miss, _soulshot); } } - class AttackTask extends TimerTask + class AttackTask implements Runnable { Creature _instance; @@ -1519,18 +1485,11 @@ public abstract class Creature extends WorldObject @Override public void run() { - try - { - _instance.onAttackTimer(); - } - catch (Exception e) - { - _log.severe(e.toString()); - } + _instance.onAttackTimer(); } } - class ArriveTask extends TimerTask + class ArriveTask implements Runnable { Creature _instance; @@ -1542,15 +1501,8 @@ public abstract class Creature extends WorldObject @Override public void run() { - try - { - _instance.onTargetReached(); - } - catch (Exception e) - { - _log.severe(e.toString()); - } - _currentMoveTask = null; + _instance.onTargetReached(); + _moveTask = null; } } @@ -1564,13 +1516,9 @@ public abstract class Creature extends WorldObject setX(x); setY(y); setZ(z); - try + ThreadPool.schedule(() -> { - Thread.sleep(2000); - } - catch (InterruptedException e) - { - } - World.getInstance().addVisibleObject(this); + World.getInstance().addVisibleObject(this); + }, 2000); } } diff --git a/L2J_Mobius_C1_HarbingersOfWar/java/org/l2jmobius/gameserver/model/actor/instance/NpcInstance.java b/L2J_Mobius_C1_HarbingersOfWar/java/org/l2jmobius/gameserver/model/actor/instance/NpcInstance.java index f0d6873b19..dd826c79c8 100644 --- a/L2J_Mobius_C1_HarbingersOfWar/java/org/l2jmobius/gameserver/model/actor/instance/NpcInstance.java +++ b/L2J_Mobius_C1_HarbingersOfWar/java/org/l2jmobius/gameserver/model/actor/instance/NpcInstance.java @@ -19,7 +19,7 @@ package org.l2jmobius.gameserver.model.actor.instance; import java.io.File; import java.io.FileInputStream; -import java.util.Timer; +import java.util.concurrent.ScheduledFuture; import java.util.logging.Logger; import org.l2jmobius.Config; @@ -36,6 +36,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; public class NpcInstance extends Creature { @@ -49,8 +50,7 @@ public class NpcInstance extends Creature private int _spReward; private int _attackRange; private boolean _aggressive; - private Creature.DecayTask _decayTask; - private static Timer _decayTimer = new Timer(true); + private ScheduledFuture _decayTask; private Spawn _spawn; public NpcInstance(Npc template) @@ -260,32 +260,19 @@ public class NpcInstance extends Creature } else { - FileInputStream fis = null; try { - fis = new FileInputStream(file); + FileInputStream fis = new FileInputStream(file); final byte[] raw = new byte[fis.available()]; fis.read(raw); final String content = new String(raw, "UTF-8"); insertObjectIdAndShowChatWindow(player, content); + fis.close(); } catch (Exception e) { _log.warning("problem with npc text " + e); } - finally - { - try - { - if (fis != null) - { - fis.close(); - } - } - catch (Exception e1) - { - } - } } player.sendPacket(new ActionFailed()); } @@ -330,10 +317,9 @@ public class NpcInstance extends Creature final NpcInstance NpcInstance = this; synchronized (NpcInstance) { - if (_decayTask == null) + if ((_decayTask == null) || _decayTask.isCancelled() || _decayTask.isDone()) { - _decayTask = new Creature.DecayTask(this); - _decayTimer.schedule(_decayTask, 7000L); + _decayTask = ThreadPool.schedule(new Creature.DecayTask(this), 7000); } } } diff --git a/L2J_Mobius_C1_HarbingersOfWar/java/org/l2jmobius/gameserver/model/actor/instance/PetInstance.java b/L2J_Mobius_C1_HarbingersOfWar/java/org/l2jmobius/gameserver/model/actor/instance/PetInstance.java index 84925be0e9..91beee0b14 100644 --- a/L2J_Mobius_C1_HarbingersOfWar/java/org/l2jmobius/gameserver/model/actor/instance/PetInstance.java +++ b/L2J_Mobius_C1_HarbingersOfWar/java/org/l2jmobius/gameserver/model/actor/instance/PetInstance.java @@ -17,7 +17,7 @@ */ package org.l2jmobius.gameserver.model.actor.instance; -import java.util.Timer; +import java.util.concurrent.ScheduledFuture; import java.util.logging.Logger; import org.l2jmobius.gameserver.data.ExperienceTable; @@ -47,6 +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; public class PetInstance extends Creature { @@ -64,8 +65,7 @@ public class PetInstance extends Creature private final Npc _template; private int _attackRange = 36; private boolean _follow = true; - private Creature.DecayTask _decayTask; - private static Timer _decayTimer = new Timer(true); + private ScheduledFuture _decayTask; private int _controlItemId; private int _nextLevel; private int _lastLevel; @@ -403,10 +403,9 @@ public class PetInstance extends Creature final PetInstance PetInstance = this; synchronized (PetInstance) { - if (_decayTask == null) + if ((_decayTask == null) || _decayTask.isCancelled() || _decayTask.isDone()) { - _decayTask = new Creature.DecayTask(this); - _decayTimer.schedule(_decayTask, 10000L); + _decayTask = ThreadPool.schedule(new Creature.DecayTask(this), 7000); } } } diff --git a/L2J_Mobius_C1_HarbingersOfWar/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java b/L2J_Mobius_C1_HarbingersOfWar/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java index 750cbbc113..78cf57a92c 100644 --- a/L2J_Mobius_C1_HarbingersOfWar/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java +++ b/L2J_Mobius_C1_HarbingersOfWar/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java @@ -21,9 +21,9 @@ import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Timer; -import java.util.TimerTask; import java.util.TreeMap; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ScheduledFuture; import java.util.logging.Logger; import org.l2jmobius.Config; @@ -80,16 +80,15 @@ 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.util.Rnd; public class PlayerInstance extends Creature { private static Logger _log = Logger.getLogger(PlayerInstance.class.getName()); - private static Timer _magicUseTimer = new Timer(true); - private static Timer _enableSkillTimer = new Timer(true); - private static Timer _enableAllSkillsTimer = new Timer(true); - private final Map _disabledSkills = new HashMap<>(); - private boolean _allSkillsDisabled = false; + + private final Map _disabledSkills = new ConcurrentHashMap<>(); + private volatile boolean _allSkillsDisabled = false; private Connection _netConnection; private int _charId = 199546; private int _canCraft = 0; @@ -100,7 +99,7 @@ public class PlayerInstance extends Creature private int _pkKills; private int _pvpFlag = 0; private long _lastPvpTime; - private static Timer _pvpTimer = null; + private ScheduledFuture _pvpTask; private int _maxLoad; private int _race; private int _classId; @@ -135,7 +134,7 @@ public class PlayerInstance extends Creature private long _uptime; public byte updateKnownCounter = 0; private Creature _interactTarget; - private static Timer _waterTimer = null; + private ScheduledFuture _waterTask; public Skill addSkill(Skill newSkill) { @@ -417,10 +416,10 @@ public class PlayerInstance extends Creature private void stopPvPFlag() { - if (_pvpTimer != null) + if (_pvpTask != null) { - _pvpTimer.cancel(); - _pvpTimer = null; + _pvpTask.cancel(true); + _pvpTask = null; } updatePvPFlag(0); } @@ -433,10 +432,9 @@ public class PlayerInstance extends Creature } if (value == 1) { - if (_pvpTimer == null) + if (_pvpTask == null) { - _pvpTimer = new Timer(); - _pvpTimer.schedule(new pvpTask(), 1000, 1000); + _pvpTask = ThreadPool.scheduleAtFixedRate(new pvpTask(), 1000, 1000); } _lastPvpTime = System.currentTimeMillis() + 30000; } @@ -450,25 +448,19 @@ public class PlayerInstance extends Creature broadcastPacket(userInfo); } - class pvpTask extends TimerTask + class pvpTask implements Runnable { @Override public void run() { - try + final long currentTime = System.currentTimeMillis(); + if (currentTime > _lastPvpTime) { - final long currentTime = System.currentTimeMillis(); - if (currentTime > _lastPvpTime) - { - stopPvPFlag(); - } - else if (currentTime > (_lastPvpTime - 5000)) - { - updatePvPFlag(2); - } + stopPvPFlag(); } - catch (Throwable e) + else if (currentTime > (_lastPvpTime - 5000)) { + updatePvPFlag(2); } } } @@ -1558,9 +1550,62 @@ public class PlayerInstance extends Creature { disableSkill(skill.getId(), true); disableAllSkills(); - _magicUseTimer.schedule(new MagicUseTask(target, skill), skill.getHitTime()); - _enableSkillTimer.schedule(new EnableSkill(skill.getId()), skill.getReuseDelay()); - _enableAllSkillsTimer.schedule(new EnableAllSkills(skill), skill.getSkillTime()); + ThreadPool.schedule(new MagicUseTask(target, skill), skill.getHitTime()); + ThreadPool.schedule(new EnableSkill(skill.getId()), skill.getReuseDelay()); + ThreadPool.schedule(new EnableAllSkills(skill), skill.getSkillTime()); + } + } + + private class MagicUseTask implements Runnable + { + Creature _target; + Skill _skill; + + public MagicUseTask(Creature target, Skill skill) + { + _target = target; + _skill = skill; + } + + @Override + public void run() + { + onMagicUseTimer(_target, _skill); + } + } + + private class EnableSkill implements Runnable + { + int _skillId; + + public EnableSkill(int skillId) + { + _skillId = skillId; + } + + @Override + public void run() + { + disableSkill(_skillId, false); + } + } + + private class EnableAllSkills implements Runnable + { + Skill _skill; + + public EnableAllSkills(Skill skill) + { + _skill = skill; + } + + @Override + public void run() + { + if (getSkill() == _skill) + { + enableAllSkills(); + } } } @@ -1678,14 +1723,16 @@ public class PlayerInstance extends Creature public boolean isSkillDisabled(int skillId) { - try - { - return _disabledSkills.get(skillId); - } - catch (NullPointerException e) + if (!_disabledSkills.containsKey(skillId)) { return false; } + return _disabledSkills.get(skillId); + } + + public boolean isAllSkillsDisabled() + { + return _allSkillsDisabled; } public void disableAllSkills() @@ -1694,7 +1741,7 @@ public class PlayerInstance extends Creature } @Override - protected void enableAllSkills() + public void enableAllSkills() { _allSkillsDisabled = false; } @@ -1763,66 +1810,6 @@ public class PlayerInstance extends Creature broadcastPacket(msc); } - class EnableAllSkills extends TimerTask - { - Skill _skill; - - public EnableAllSkills(Skill skill) - { - _skill = skill; - } - - @Override - public void run() - { - if (getSkill() == _skill) - { - enableAllSkills(); - } - } - } - - class EnableSkill extends TimerTask - { - int _skillId; - - public EnableSkill(int skillId) - { - _skillId = skillId; - } - - @Override - public void run() - { - disableSkill(_skillId, false); - } - } - - class MagicUseTask extends TimerTask - { - Creature _target; - Skill _skill; - - public MagicUseTask(Creature target, Skill skill) - { - _target = target; - _skill = skill; - } - - @Override - public void run() - { - try - { - onMagicUseTimer(_target, _skill); - } - catch (Exception e) - { - e.printStackTrace(); - } - } - } - public void checkWaterState() { // Water level. @@ -1859,30 +1846,29 @@ public class PlayerInstance extends Creature public boolean isInWater() { - return _waterTimer != null; + return _waterTask != null; } private void startWaterTask() { - if ((_waterTimer == null) && !isDead()) + if ((_waterTask == null) && !isDead()) { - _waterTimer = new Timer(); - _waterTimer.schedule(new waterTask(this), 86000, 1000); + _waterTask = ThreadPool.scheduleAtFixedRate(new waterTask(this), 86000, 1000); sendPacket(new SetupGauge(SetupGauge.CYAN, 86000)); } } private void stopWaterTask() { - if (_waterTimer != null) + if (_waterTask != null) { - _waterTimer.cancel(); - _waterTimer = null; + _waterTask.cancel(true); + _waterTask = null; sendPacket(new SetupGauge(SetupGauge.CYAN, 0)); } } - class waterTask extends TimerTask + class waterTask implements Runnable { private final PlayerInstance _player; @@ -1894,22 +1880,16 @@ public class PlayerInstance extends Creature @Override public void run() { - try - { - int reduceHp = (int) (getMaxHp() / 100.0); - if (reduceHp < 1) - { - reduceHp = 1; - } - - reduceCurrentHp(reduceHp, _player, false); - final SystemMessage sm = new SystemMessage(SystemMessage.DROWN_DAMAGE_S1); - sm.addNumber(reduceHp); - sendPacket(sm); - } - catch (Throwable e) + int reduceHp = (int) (getMaxHp() / 100.0); + if (reduceHp < 1) { + reduceHp = 1; } + + reduceCurrentHp(reduceHp, _player, false); + final SystemMessage sm = new SystemMessage(SystemMessage.DROWN_DAMAGE_S1); + sm.addNumber(reduceHp); + sendPacket(sm); } } diff --git a/L2J_Mobius_C1_HarbingersOfWar/java/org/l2jmobius/gameserver/threadpool/RejectedExecutionHandlerImpl.java b/L2J_Mobius_C1_HarbingersOfWar/java/org/l2jmobius/gameserver/threadpool/RejectedExecutionHandlerImpl.java new file mode 100644 index 0000000000..435ade2c54 --- /dev/null +++ b/L2J_Mobius_C1_HarbingersOfWar/java/org/l2jmobius/gameserver/threadpool/RejectedExecutionHandlerImpl.java @@ -0,0 +1,51 @@ +/* + * 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.RejectedExecutionException; +import java.util.concurrent.RejectedExecutionHandler; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.logging.Logger; + +/** + * @author NB4L1 + */ +public class RejectedExecutionHandlerImpl implements RejectedExecutionHandler +{ + private static final Logger LOGGER = Logger.getLogger(RejectedExecutionHandlerImpl.class.getName()); + + @Override + public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) + { + if (executor.isShutdown()) + { + return; + } + + LOGGER.warning(r + " from " + executor + " " + new RejectedExecutionException()); + + if (Thread.currentThread().getPriority() > Thread.NORM_PRIORITY) + { + new Thread(r).start(); + } + else + { + r.run(); + } + } +} diff --git a/L2J_Mobius_C1_HarbingersOfWar/java/org/l2jmobius/gameserver/threadpool/RunnableWrapper.java b/L2J_Mobius_C1_HarbingersOfWar/java/org/l2jmobius/gameserver/threadpool/RunnableWrapper.java new file mode 100644 index 0000000000..45c694c6fe --- /dev/null +++ b/L2J_Mobius_C1_HarbingersOfWar/java/org/l2jmobius/gameserver/threadpool/RunnableWrapper.java @@ -0,0 +1,51 @@ +/* + * 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.lang.Thread.UncaughtExceptionHandler; + +/** + * @author Mobius + */ +public class RunnableWrapper implements Runnable +{ + private final Runnable _runnable; + + public RunnableWrapper(Runnable runnable) + { + _runnable = runnable; + } + + @Override + public void run() + { + try + { + _runnable.run(); + } + catch (Throwable e) + { + final Thread t = Thread.currentThread(); + final UncaughtExceptionHandler h = t.getUncaughtExceptionHandler(); + if (h != null) + { + h.uncaughtException(t, e); + } + } + } +} diff --git a/L2J_Mobius_C1_HarbingersOfWar/java/org/l2jmobius/gameserver/threadpool/ThreadPool.java b/L2J_Mobius_C1_HarbingersOfWar/java/org/l2jmobius/gameserver/threadpool/ThreadPool.java new file mode 100644 index 0000000000..bafc6ab129 --- /dev/null +++ b/L2J_Mobius_C1_HarbingersOfWar/java/org/l2jmobius/gameserver/threadpool/ThreadPool.java @@ -0,0 +1,172 @@ +/* + * 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.
+ * It relies on two threadpool executors, which pool size is set using config.
+ * Those arrays hold following pools:
+ *
    + *
  • Scheduled pool keeps a track about incoming, future events.
  • + *
  • Instant pool handles short-life events.
  • + *
+ */ +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(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(() -> + { + 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) + { + t.printStackTrace(); + } + } +} \ No newline at end of file