目前,我正在使用计时器来执行我的技能效果。所有技能效果每3秒做一次心跳。
这是我的密码:
public class EffectServiceImpl extends AbsServiceAdaptor<EffectConfig> {
private static EffectServiceImpl instance;
private FastList<Monster> existsEffectMonsterList;
private Timer timer;
public static EffectServiceImpl getInstance() {
if(null == instance) {
instance = new EffectServiceImpl();
}
return instance;
}
private EffectServiceImpl() {
existsEffectMonsterList = new FastList<Monster>();
timer = new Timer();
timer.schedule(new MonsterEffectCheckTask(), 10000, 3000); // Heartbeat every 3 seconds
}
public class MonsterEffectCheckTask extends TimerTask {
@Override
public void run() {
if(existsEffectMonsterList.size() > 0) {
Monster monster;
Effect effect;
for(int i = 0; i < existsEffectMonsterList.size();) {
monster = existsEffectMonsterList.get(i);
if(monster.effectList.size() > 0) {
for(int j = 0; j < monster.effectList.size();) {
try {
effect = monster.effectList.get(j);
if(effect.heartbeat(monster)) {
j++;
}
}
catch(Exception e) {
e.printStackTrace();
break;
}
}
}
if(monster.effectList.size() == 0) {
existsEffectMonsterList.remove(i);
}
else {
i++;
}
}
}
}
}
}
不过,我不希望所有的技能效果做心跳3秒。将有心跳技能小于3秒或大于3秒(即动态周期)。
所以我改了时间 timer.schedule
至1:
...
timer.schedule(new MonsterEffectCheckTask(), 10000, 1);
...
然后添加 Thread.sleep
到timertask:
...
if(monster.effectList.size() > 0) {
for(int j = 0; j < monster.effectList.size();) {
try {
effect = monster.effectList.get(j);
if(effect.heartbeat(monster)) {
j++;
}
Thread.sleep(effect.execTime); // This is dynamic time, each effect has an `execTime`. Code `public int execTime;`
}
catch(InterruptedException e) {
e.printStackTrace();
}
catch(Exception e) {
e.printStackTrace();
break;
}
}
}
...
对于上面这样的代码,我应该:使用 schedule
或者 scheduleAtFixedRate
或者其他什么?有什么办法可以替换吗 Thread.sleep
万一你想“暂停”计时器?我应该设置什么 delay
以及 period
(我知道如果我把它设为0,我会得到一个 IllegalArgumentException
,但如果设置为1则太短)?我想效果是心跳后,立即“暂停”的时间已经过了。此外,在同一心跳中可能有许多效果,但每个效果的“暂停”时间并不相同。
谢谢你的回答。
1条答案
按热度按时间t1rydlwq1#
执行者框架
Timer
现在执行者框架已经过时了。请参见oracle的教程。将您的任务定义为
Runnable
或者Callable
物体。使用由适当数量的线程支持的计划执行器服务。然后安排每个任务按您选择的时间间隔重复运行。
要检查或取消每个任务,请捕获
ScheduledFuture
对象返回给您。如果要更改任务执行之间的时间间隔,请通过其
ScheduledFuture
对象。然后使用执行器服务重新安排新的时间间隔。始终在应用程序结束前关闭executor服务。否则,后台线程池可能会像僵尸一样无限期地继续运行?。
并 Package 您的任务代码以捕获任何意外出现的异常。否则,未来的工作将悄无声息地停止。
所有这些都在堆栈溢出上被多次讨论过。所以我很简短。搜索以了解更多信息。下一次,在发布之前彻底搜索堆栈溢出。
示例代码
我制作了一个示例应用程序来展示如何使用executors框架更简单、更强大地管理后台线程工作。
我们定义一个
Monster
接口,有两个实现类,Demon
&Witch
. 我创建了这些类的一些对象。这些课程有一个actOut
方法。我们的后台任务是运行这个方法。对于每个现有的
Monster
例如,我们定义一个Runnable
也就是说Monster::actOut
方法。我们通过一个ScheduledExecutorService
对象。执行器服务返回ScheduledFuture
对象来跟踪我们计划的每个runnable。我们将这些未来的对象收集到Demon
以及一份Witch
.我们让它运行一分钟。过了这段时间,我们改变了音乐的节奏
Witch
任务。我们取消它们当前的任务,然后在两次执行之间安排一个新的可运行对象更长的时间间隔。我们让它再运行一分钟。之后,我们关闭应用程序。(顺便说一句,我们可以回收现有的
Runnable
对象,而不是在重新调度时示例化新对象。做任何对你的需要有意义的事。)这段代码使用了Java15中预览的一些即将推出的特性,比如密封类型和记录。但这些对这里的概念并不重要;您可以使用以前版本的java轻松地重新编写这段代码。
样品运行
运行示例:
源代码
我们有四节课:
Monster.java
(我们业务对象的接口)Demon.java
(混凝土等级)Witch.java
(混凝土等级)MonsterMash.java
(应用程序类)代码: