Executor: ------------------------------------------------ package net.sf.l2j.gameserver.model.job; import java.util.LinkedList; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; /** * @author zabbix * * Global tasks thread * */ public class L2ExecutorService { private static LinkedList _dequeue = new LinkedList(); private static ScheduledThreadPoolExecutor _executorService; private static L2ExecutorService _instance = null; public L2ExecutorService() { _executorService = new ScheduledThreadPoolExecutor(1, new ExecutorThreadFactory("ExecSvc", Thread.NORM_PRIORITY+1)); _executorService.scheduleAtFixedRate(new ExecuteJobs(),1000,100,TimeUnit.MILLISECONDS); } public static L2ExecutorService getInstance() { if(_instance == null) _instance = new L2ExecutorService(); return _instance; } private class ExecuteJobs implements Runnable { public void run() { synchronized(_dequeue) { int _jobsCount = _dequeue.size(); long serverFrame = System.currentTimeMillis(); for(int i=0;i<_jobsCount;i++) { L2Job job = _dequeue.poll(); if(job.getState() == L2JobState.JOBSTATE_TERMINATED) { _jobsCount--; continue; } if((serverFrame - job._frameOld) >= job._frameTime) job.Tick(); _dequeue.addLast(job); } } } } public L2Job addJob(L2Job job) { synchronized(_dequeue) { _dequeue.addLast(job); } return job; } public synchronized void flushJob(L2Job job) { int sp = _dequeue.indexOf(job); if(sp >= 0) _dequeue.get(sp).Terminate(); } public String getStats() { String ret = "====== L2ExecutorService stats ======\r\n"; synchronized(_dequeue) { ret += "Dequeue size: "+_dequeue.size()+"\r\n"; for (L2Job job : _dequeue) { ret += "Job: "+job._type+" period: "+job._frameTime+" state: "+job.getState()+"\r\n"; } } return ret; } private class ExecutorThreadFactory implements ThreadFactory { private int _prio; private String _name; private AtomicInteger _threadNumber = new AtomicInteger(1); public ExecutorThreadFactory(String name, int prio) { _prio = prio; _name = name; } /* (non-Javadoc) * @see java.util.concurrent.ThreadFactory#newThread(java.lang.Runnable) */ public Thread newThread(Runnable r) { Thread t = new Thread(r); t.setName(_name+"-"+_threadNumber.getAndIncrement()); t.setPriority(_prio); return t; } } } L2Job superclass #1: ------------------------------------------------ package net.sf.l2j.gameserver.model.job; public abstract class L2Job { private int _owner; // owning L2Object protected L2JobType _type; private L2JobState _state; protected long _frameTime; protected long _frameOld; public L2Job() { _state = L2JobState.JOBSTATE_EXECUTION; _frameOld = System.currentTimeMillis(); } public void Terminate() { _state = L2JobState.JOBSTATE_TERMINATED; } public void Tick() { _frameOld = System.currentTimeMillis(); } public L2JobState getState() { return _state; } public void setOwner(int owner) { _owner = owner; } public int getOwner() { return _owner; } } L2Job superclass #2: ------------------------------------------------ package net.sf.l2j.gameserver.model.job; public enum L2JobState { JOBSTATE_EXECUTION, JOBSTATE_TERMINATED } L2Job Superclass #3: ------------------------------------------------ package net.sf.l2j.gameserver.model.job; public enum L2JobType { JOB_FOLLOW, JOB_HIT_TASK, JOB_NOTIFY_AI, JOB_EVTTHINK_AI, JOB_ENABLE_SKILL, JOB_EFFECT } Job example #1: ------------------------------------------------ package net.sf.l2j.gameserver.model.job; import net.sf.l2j.gameserver.ai.CtrlEvent; import net.sf.l2j.gameserver.model.L2Character; import net.sf.l2j.gameserver.model.L2World; public class JobNotifyAI extends L2Job { CtrlEvent _evt; public JobNotifyAI(int owner,CtrlEvent evt, long delay) { super(); setOwner(owner); _evt = evt; _frameTime = delay; _type = L2JobType.JOB_NOTIFY_AI; } public void Tick() { super.Tick(); L2Character owner = L2World.getInstance().safeCastCreature("notiyAITick",getOwner()); if(owner != null && owner.getAI() != null) owner.getAI().notifyEvent(_evt,null); Terminate(); } } Job example #2: ------------------------------------------------ package net.sf.l2j.gameserver.model.job; import net.sf.l2j.gameserver.model.L2Character; import net.sf.l2j.gameserver.model.L2World; public class JobHitTask extends L2Job { int _target; int _dmg; boolean _crit; boolean _miss; boolean _ss; boolean _shield; public JobHitTask(int owner,int target, int damage, boolean crit, boolean miss, boolean soulshot, boolean shld, long delay) { super(); setOwner(owner); _target = target; _dmg = damage; _crit = crit; _miss = miss; _ss = soulshot; _shield = shld; _frameTime = delay; _type = L2JobType.JOB_HIT_TASK; } public void Tick() { super.Tick(); L2Character actor = L2World.getInstance().safeCastCreature("hitTickActor",getOwner()); L2Character target = L2World.getInstance().safeCastCreature("hitTickTarget",_target); //FIXME: // target может быть null // это отрабатывается в onHitTimer (AINotifyEvent.CANCEL) if(actor != null) actor.onHitTimer(target,_dmg,_crit,_miss,_ss,_shield); Terminate(); } }