单线程(schedule)与多线程(ScheduledExecutorService)实现定时器任务管理及查询
2018-02-12 14:26
609 查看
0、序
在游戏工程地开发过程中,定时器功能是一般游戏必不可少的功能,同时,在其他类型的项目中,也会时常需要用到定时器的方法。例如游戏中建造一个建筑需要倒计时等。下面从单线程和多线程两个方面实现定时器的功能。1、单线程(schedule)
首先我们需要一个单独的定时任务类,继承TimerTask,用来表示具体的定时任务,单独提出来封装成一个类,方便管理和实现:import java.util.TimerTask;import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Future;
public class SystemTimerTask extends TimerTask{
private long taskID;//任务ID
private long runtime;//倒计时的具体时间(以秒为单位)
private ConcurrentHashMap<Long, Future<Long>> futureMap;
public SystemTimerTask(Long taskID,long runtime) {
this.taskID = taskID;
this.runtime = runtime;
}
@Override
public void run() {
System.out.println("Time Remain: "+this.runtime);
if (this.runtime-- <= 0 ) {
try {
Future<Long> future = futureMap.remove(taskID);
future.cancel(true);
} finally {
System.out.println("###### Task "+taskID +" is Completed!!");
}
}
}
public long getRemaintime() { return runtime; }
public long getTaskID() { return taskID; }
}
在单线程的情况下,不需要考虑其他条件直接调用 schedule 方法即可实现,具体调用方法如下:Timer timer = new Timer();
SystemTimerTask() task = new SystemTimerTask(10001,20);
timer.schedule(task ,0,1000); 关于schedule 方法声明为:schedule(TimerTask task, long delay, long period)
--task:被调度的定时任务;
--delay:以毫秒为单位,表示任务延迟delay毫秒后执行;
--period:以毫秒为单位,表示任务执行持续时间,也就是定时器初始值。
2、多线程(ScheduledExecutorService)
在实际应用开发中,单线程应用的范围很窄,并发是项目开发中必不可少的需要考虑到的因素,在定时器实现中,采用多线程,可以更有效率地实现多个定时器并发操作,同时,可以在一个大的项目中,对定时任务线程实施更方便地管理和查看。所以,我们在Java内置定时任务线程池ScheduledExecutorService基础上,封装成一个定时任务线程管理类,如下:import java.util.Iterator; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; //根据具体包名,将SystemTimerTask包含进来 public class TimerManager { private static TimerManager instance; private TimerManager() { } public static TimerManager getInstance() { if(instance == null) { return new TimerManager(); } return instance; } private ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor(); //初始化ScheduledExecutorService线程池,具体长度视情况而定 private static ConcurrentHashMap<Long, SystemTimerTask> taskmap = new ConcurrentHashMap<Long, SystemTimerTask>();//采用以任务ID为key的哈希表存储所有实现的定时任务 public boolean StartTimer(long id,long time,long initialDelay, long period, TimeUnit unit ) { if(taskmap.containsKey(id) ) { return false; } else { SystemTimerTask task_time = new SystemTimerTask(id,time); this.addTask(id, task_time); Iterator keys = taskmap.keySet().iterator(); while(keys.hasNext()){ Long key = (Long)keys.next(); if(key == id) System.out.println("是否存在------------- "+ (key == id)+" id: "+id); } System.out.println("是否存在+++++++++++ "+ taskmap.get(id).getRemaintime()); this.service.scheduleAtFixedRate(task_time, initialDelay,period, unit); return true; } } public ScheduledExecutorService getService() { return service; } public void setService(ScheduledExecutorService service) { this.service = service; } public long getRemain(long id) { if(this.getTask().containsKey(id)) { return this.getTask().get(id).getRemaintime(); } else return -1; } public ConcurrentHashMap<Long, SystemTimerTask> getTask() { return taskmap; } public void addTask( long id ,SystemTimerTask task1) { taskmap.put(id, task1) ; }}以上将定时器管理类设置为单例模式,防止其他对象对自己实例化,确保所有对象访问的都是一个实例。
scheduleAtFixedRate 方法的参数说明同上面的 Timer类中的 schedule 方法。可自行查阅。 以下为其测试主函数:public static void main(String[] args) throws InterruptedException {
long remain = 10;
long remain2 = 20;
System.out.println("Start:");
long id1 = 100;
long id2 = 110;
TimerManager.getInstance().StartTimer(id1, remain, 0, 1, TimeUnit.SECONDS);
TimerManager.getInstance().StartTimer(id2, remain2, 0, 1, TimeUnit.SECONDS);
Thread.sleep(3000);
System.out.println("是否存在::::"+ TimerManager.getInstance().getTask().containsKey(id1));
System.out.println("+++++++++++++++++++++Time remain................ :"+TimerManager.getInstance().getRemain(id2));
}
3、总结
在本文中,基于单线程和多线程两种方式实现定时器的功能,两种各有优缺点,合理采纳。同时,在多线程实现中,有一点不足之处,在具体应用的时候希望改正,就是定时任务ID可以采用自动生成的增长序列,保证其唯一性,因为时间关系,本文尚未添加。相关文章推荐
- 任务调度(四)——ScheduledExecutorService替代Timer,实现多线程任务调度
- 定时任务实现Timer, TimeTask, ScheduledExecutorService及Spring定时器
- 定时任务实现Timer, TimeTask, ScheduledExecutorService及Spring定时器
- 定时任务实现Timer, TimeTask, ScheduledExecutorService及Spring定时器
- 任务调度(四)——ScheduledExecutorService替代Timer,实现多线程任务调度
- Timer管理延时任务的缺陷,和ScheduledExecutorService替代
- ScheduledExecutorService实现定时器-定时发邮件
- Spring定时任务的实现方式--ScheduledExecutorService and ScheduledExecutorFactoryBean的简单源码解析以及使用
- 利用ScheduledExecutorService实现定时任务
- 用 ScheduledExecutorService 实现的任务功能Demo
- Spring定时任务的实现方式--ScheduledExecutorService
- Android实现调度任务的三种方式:TimerTask、ScheduledExecutorService、Handler
- 用ScheduledExecutorService实现任务调度
- ScheduledExecutorService定时周期执行指定的任务 ,关于scheduleAtFixedRate 和 scheduleWithFixedDelay使用区别
- Java中定时任务的实现:Timer与ScheduledExecutorService的不同
- Java中定时任务的实现:Timer与ScheduledExecutorService的不同
- 多线程和并发中新的任务执行架构Executor、ExecutorService、ScheduledExecutorService
- Java中定时任务的实现:Timer与ScheduledExecutorService的不同
- 任务调度的 Java 实现方法一:Timer、TimerTask、 ScheduledExecutorService
- ScheduledExecutorService执行周期任务