使用优先队列实现游戏公告模块(Java)

一.问题描述

**实现公告消息分优先级,优先级高的公告,优先推送,同一优先在其后面加入.有点像是队列里面的分组还是队列的数据结构.

思路首先使用优先级做队列,然后根据时间戳做队列.然后定期推送.如果优先级高者加入,立刻推送,并将未播放完的公告加入队列.**

二.相关的类和方法的实现

Notice类:公告的消息体

/**
 * 公告信息体
 * 
 * @author insping
 *
 */
public class Notice {
    int priorLevel; // 优先级
    long time; // 消息的时间戳
    Object obj; // 公告体,可以是任意对象

    public Notice() {

    }

    public Notice(int priorLevel, long time, Object obj) {
        this.priorLevel = priorLevel;
        this.time = time;
        this.obj = obj;
    }

    public int getPriorLevel() {
        return priorLevel;
    }

    public void setPriorLevel(int priorLevel) {
        this.priorLevel = priorLevel;
    }

    public long getTime() {
        return time;
    }

    public void setTime(long time) {
        this.time = time;
    }

    public Object getObj() {
        return obj;
    }

    public void setObj(Object obj) {
        this.obj = obj;
    }

}

NoticeManager类:公告的管理类

import java.util.Comparator;
import java.util.PriorityQueue;

public class NoticeManager {
    private static NoticeManager instance = new NoticeManager();

    public static NoticeManager getInstance() {
        return instance;
    }

    public PriorityQueue<Notice> worldNotices = new PriorityQueue<Notice>(11, new Comparator<Notice>() {
        @Override
        public int compare(Notice o1, Notice o2) {
            int numbera = o1.getPriorLevel();
            int numberb = o2.getPriorLevel();
            long timea = o1.getTime();
            long timeb = o2.getTime();
            return numberb == numbera ? (timea == timeb ? 0 : (timea < timeb ? -1 : 1)) : (numbera > numberb ? -1 : 1);
        }
    });// 世界公告
    long noticeStart = System.currentTimeMillis(); // 公告消息的时间
    Notice priorNotice = new Notice();// 用作记录上次所发送的公告

    /**
     * 发送一条公告消息(优先展示)
     * 
     * @param msg
     */
    public void addNotice(Notice noticeMsg) {
        synchronized (worldNotices) {
            worldNotices.add(noticeMsg);
            if (noticeMsg.getPriorLevel() > priorNotice.getPriorLevel() && priorNotice.getTime() != 0) {
                worldNotices.add(priorNotice);
                noticeStart = 0; // 让头数据立刻下发
            }
        }
    }

    /**
     * 推送一条公告消息
     */
    public boolean sendHeadWorldNotice() {
        synchronized (worldNotices) {
            Notice noticeMsg = worldNotices.poll();
            if (noticeMsg == null) {
                return false;
            }
            priorNotice = noticeMsg;
            // 想所有在线的玩家推送notice
            // sendToAllRole(noticeMsg);
            System.out.println(noticeMsg.getObj()); //做测试显示.
            return true;
        }
    }

    /**
     * 定期向所有在线的用户 发送公告消息
     */
    public boolean sendHeadWorldNoticeToAllOnlineRoles() {
        // 刷新公告信息
        synchronized (worldNotices) {
            if (worldNotices.size() > 0 && System.currentTimeMillis() - noticeStart >= 20 * 1000) {
                if (!sendHeadWorldNotice()) {
                    return false;
                }
                noticeStart = System.currentTimeMillis();
                return true;
            }
            return false;
        }
    }
}

NoticeThread类:公告线程


public class NoticeThread extends Thread implements Instance {
    @Override
    public void run() {
        while (1 != 0) // !ServiceApp.FREEZE 可以判断服务的状态
            try {
                noticeMgr.sendHeadWorldNoticeToAllOnlineRoles();
            } catch (Exception e) {
                System.out.println(e);
            }
    }
}

Instance接口


public interface Instance {
    public static final NoticeManager noticeMgr = NoticeManager.getInstance();
}

测试程序:

    public static void main(String args[]) throws InterruptedException {
        NoticeThread noticeThread = new NoticeThread();
        noticeThread.start();
        Notice noticeMsg = new Notice(2,System.currentTimeMillis(), (Object) 1);
        noticeMgr.addNotice(noticeMsg);
        noticeMgr.sendHeadWorldNotice();
        Thread.sleep(1000);
        Notice noticeMsg1 = new Notice(1, System.currentTimeMillis(), (Object) 2);
        noticeMgr.addNotice(noticeMsg1);
        Thread.sleep(1000);
        Notice noticeMsg2 = new Notice(2, System.currentTimeMillis(), (Object) 4);
        noticeMgr.addNotice(noticeMsg2);
        Thread.sleep(1000);
        Notice noticeMsg3 = new Notice(3, System.currentTimeMillis(), (Object) 3);
        noticeMgr.addNotice(noticeMsg3);
        }

结果:
1
3
1
4
2

运行环境 操作系统:Windows XP。 Java平台:JDK 1.5。 Web服务器:Tomcat v 5.5.23,下载地址:http://tomcat.apache.org/。 数据库服务器:MySQL v 5.0.45,下载地址:http://www.mysql.com/。 开发平台:Eclipse SDK v 3.2.2,下载地址:http://www.eclipse.org/download/index.jsp。 Eclipse插件TomcatPlugins v 3.2.1,下载地址:http://www.eclipse-plugins.info/eclipse/index.jsp。 Eclipse插件ResourceBundleEditor v 0.7.7,下载地址:http://resourcebundleeditor.com/。 Eclipse插件MyEclipse v 5.5.1,下载地址:http://www.myeclipseide.com/ Spring 采用 2.0 版本 Hibernate 采用3.0版本 ============================ 请注意:如出现中文乱码,检查如下配置是否正确。 (1)MySql 数据库是否是utf-8 格式(在安装时选择支持多语言),数据是否正常。 (2)项目是否为utf-8格式(同时看看的源代码文件中,中文是否乱码)。 (3)JSP页面是否是utf-8 格式。 (4)在web.xml 是否配置了编码过滤器。 (5)数据源配置的url(?useUnicode=true&characterEncoding=UTF-8),具体请看项目实例。 如果上面5步都没问题,你就不存在中文乱码问题。 ============================== 数据库使用的是MySQL,其版本为5.0.45 版本。 数据库的用户名及密码均为root。 使用的时候,请参考附件数据库导入一节。或将需要用到的某章的数据库目录复制到“mysql安装根目录\data”文件夹下就可以了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值