单线程(schedule)与多线程(ScheduledExecutorService)实现定时器任务管理及查询

本文介绍如何在单线程和多线程环境中实现定时器功能,包括使用Java的TimerTask和ScheduledExecutorService进行定时任务调度的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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 方法。可自行查阅。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可以采用自动生成的增长序列,保证其唯一性,因为时间关系,本文尚未添加。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值