您的位置:首页 > 其它

单线程(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可以采用自动生成的增长序列,保证其唯一性,因为时间关系,本文尚未添加。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  并发 定时器
相关文章推荐