开发者社区> 问答> 正文

针对同一个客户端,MINA怎么可以同时开启多个线程以不同的频率发送多种消息呢??报错

我的项目要求在客户端连接到服务器的时候,就会时时的给他每秒一次的推送数据,还有其他的数据有的是5秒一次,有的是1分一次。我试着自己建了多个线程传入ISsession 发送数据 总是报错。如果只开启一个线程就正常。

下面是hander中的代码:

@Override
	public void sessionOpened(IoSession session) throws Exception {
		System.out.println("【server】sessionOpened ID:" + session.getId());
		if (allIoSessions == null) {
			allIoSessions = session.getService().getManagedSessions();
		}
		System.out.println("有人连接,当前客户数:" + allIoSessions.size());
		new Thread(new AllPoliceCoordsThread(session, service)).start();
		new Thread(new HotPoliceCoordsThread(session, service)).start();
		new Thread(new UserCoordsThread(session, service)).start();

	}

注释掉两个线程的话,只留一个(1秒发一次)就正常了。可是如果把频率改成1毫秒一次。就算一个线程也要不停地报错

展开
收起
爱吃鱼的程序员 2020-06-10 15:06:39 627 0
1 条回答
写回答
取消 提交回答
  • https://developer.aliyun.com/profile/5yerqm5bn5yqg?spm=a2c6h.12873639.0.0.6eae304abcjaIB

    增加一个队列,多线程产生的消息都先入队急求顶<preclass="brush:java;toolbar:true;auto-links:false;">packagecom.tcp.mina.main;importjava.util.ArrayList;importjava.util.Collection;importjava.util.List;importjava.util.Map;importorg.apache.mina.core.IoUtil;importorg.apache.mina.core.service.IoHandlerAdapter;importorg.apache.mina.core.session.IdleStatus;importorg.apache.mina.core.session.IoSession;importcom.safe.model.Police;importcom.safe.model.User;importcom.safe.service.CenterService;importcom.safe.util.ConstantUtil;importcom.safe.util.DateUtil;importcom.tcp.mina.frame.Frame;importcom.tcp.mina.model.M_p_HandingAlarm;importcom.tcp.mina.model.M_p_Pant;importcom.tcp.mina.model.M_p_PeopleInfo;importcom.tcp.mina.model.M_q_GetPeopleInfo;importcom.tcp.mina.model.M_q_HandingAlarm;importcom.tcp.mina.model.M_q_Pant;importcom.tcp.mina.model.PoliceTask;importcom.tcp.mina.msgcoder.MsgCoder;importcom.tcp.mina.thread.AllPoliceCoordsThread;importcom.tcp.mina.thread.HotPoliceCoordsThread;importcom.tcp.mina.thread.UserCoordsThread;importcom.tcp.mina.util.TCPConstant;publicclassMyServerHandlerextendsIoHandlerAdapter{publicstaticMap<Long,IoSession>allIoSessions;CenterServiceservice;publicMyServerHandler(CenterServiceservice){super();this.service=service;}@OverridepublicvoidexceptionCaught(IoSessionsession,Throwablecause)throwsException{System.out.println("exceptionCaught");cause.printStackTrace();}@OverridepublicvoidmessageReceived(IoSessionsession,Objectmessage)throwsException{System.out.println("【server】messageReceived:"+message);Frameframe=null;if(messageinstanceofFrame){frame=(Frame)message;}else{return;}intmsgType=frame.getMsgType();switch(msgType){/*一收到心跳/caseTCPConstant.MSGTYPE_Q_PANT:M_q_Pantm_q_Pant=newMsgCoder<M_q_Pant>().readFrame(frame,M_q_Pant.class);System.out.println("请求消息-心跳请求:"+m_q_Pant);//响应心跳M_p_Pantp_Pant=newM_p_Pant();session.write(newMsgCoder<M_p_Pant>().readMsg(p_Pant));break;/*二获取人物信息请求/caseTCPConstant.MSGTYPE_Q_PEOPLEINFO:M_q_GetPeopleInfoq_GetPeopleMsg=newMsgCoder<M_q_GetPeopleInfo>().readFrame(frame,M_q_GetPeopleInfo.class);intpeopleType=q_GetPeopleMsg.getType();if(TCPConstant.PEOPLETYPE_POLICE==peopleType){//警员Policepolice=service.getPoliceByPoliceNo(q_GetPeopleMsg.getID().trim());StringbirthdayStr=DateUtil.fmtDateToStr(police.getDetails().getBirthday(),"yyyy-MM-dd");FramepoliceFrame=newMsgCoder<M_p_PeopleInfo>().readMsg(newM_p_PeopleInfo(police.getPoliceNo(),peopleType,police.getDetails().getName(),birthdayStr,police.getDetails().getTel(),police.getDetails().getAddress(),police.getDetails().getShenFenId(),police.getDetails().getPhoto()));session.write(policeFrame);}elseif(TCPConstant.PEOPLETYPE_USER==peopleType){//用户Useruser=service.getUserByLoginName(q_GetPeopleMsg.getID().trim());StringbirthdayStr=DateUtil.fmtDateToStr(user.getDetails().getBirthday(),"yyyy-MM-dd");FrameuserFrame=newMsgCoder<M_p_PeopleInfo>().readMsg(newM_p_PeopleInfo(user.getLoginName(),peopleType,user.getDetails().getName(),birthdayStr,user.getDetails().getTel(),user.getDetails().getAddress(),user.getDetails().getShenFenId(),user.getDetails().getPhoto()));session.write(userFrame);}break;/*三处理报警请求/caseTCPConstant.MSGTYPE_Q_HANDINGALARM://解析请求消息M_q_HandingAlarmq_handingMsg=newMsgCoder<M_q_HandingAlarm>().readFrame(frame,M_q_HandingAlarm.class);//操作派警intalarmId=q_handingMsg.getEventID();inttype=q_handingMsg.getType();if(type==ConstantUtil.ALARM_TYPE_TRUE){//真警则派发任务//派发任务List<PoliceTask>policeTasks=q_handingMsg.getTask();List<String>policeNos=newArrayList<String>();StringtaskContent="";for(PoliceTaskpoliceTask:policeTasks){policeNos.add(policeTask.getPoliceID());taskContent=policeTask.getTaskInfo();}service.sendTaskAndNotice(policeNos,taskContent,alarmId);}else{//不是真警则修改对应类型1假警2重复报警//修改报警类别service.updateAlarmStatus(alarmId,type);}/*响应该报警的最新状态///发送处理报警的响应消息1这里直接返回给所有客户端,2警员提交任务时发送给所有客户端//AlarmInfoalarmInfo=service.getAlarmById();//TODO假数据M_p_HandingAlarmmsg=newM_p_HandingAlarm(alarmId,2);FramepMsgframe=newMsgCoder<M_p_HandingAlarm>().readMsg(msg);//获取所有正在连接的IoSessionCollection<IoSession>sessions=session.getService().getManagedSessions().values();//将消息写到所有IoSessionIoUtil.broadcast(pMsgframe,sessions);break;default:System.out.println("TCP:TCPListenRequest未知的请求!~");break;}//session.write(message);}@OverridepublicvoidmessageSent(IoSessionsession,Objectmessage)throwsException{System.out.println("【server】messageSent:"+message);}@OverridepublicvoidsessionClosed(IoSessionsession)throwsException{System.out.println("【server】sessionClosed");System.out.println("有人关闭,当前客户数:"+allIoSessions.size());}@OverridepublicvoidsessionCreated(IoSessionsession)throwsException{System.out.println("【server】sessionCreated");}@OverridepublicvoidsessionIdle(IoSessionsession,IdleStatusstatus)throwsException{System.out.println("【server】sessionIdle");}@OverridepublicvoidsessionOpened(IoSessionsession)throwsException{System.out.println("【server】sessionOpenedID:"+session.getId());if(allIoSessions==null){allIoSessions=session.getService().getManagedSessions();}System.out.println("有人连接,当前客户数:"+allIoSessions.size());newThread(newAllPoliceCoordsThread(session,service)).start();newThread(newHotPoliceCoordsThread(session,service)).start();newThread(newUserCoordsThread(session,service)).start();}}

    handler的完整代码。结果很惨,同时在多个线程里收发消息就会出现消息错乱了



    session加同步试试呗...

    不负责的建议

    回复<aclass='referer'target='_blank'>@颖辉小居:那三个线程难道不是你写的?直接锁住IoSession这个对象不就行了回复<aclass='referer'target='_blank'>@maradona:如果是我自己的方法我加个锁没问题,可是发送消息的IOSession是引用包里的。获得它的地方是通过重写别人的方法,得到的回复<aclass='referer'target='_blank'>@颖辉小居:你都用多线程了...不知道怎么同步?IOSession没说是线程安全的吧..这个同步锁怎么加啊?发出消息都是session直接调用的write

    时隔一年再看这个问题感触良多

    packageyh.net.mina;importorg.apache.mina.core.session.IoSession;publicclassIoSender{publicstaticvoidnoticeMsg(IoSessionsession,Objectmsg){synchronized(session){session.write(msg);}}}

    这样应该可以吧!

    为了解决服务端主动持续的多线程的向同一个Iosession(客户端)发送消息

    2020-06-10 15:06:54
    赞同 1 展开评论 打赏
问答分类:
问答地址:
问答排行榜
最热
最新

相关电子书

更多
多IO线程优化版 立即下载
探索连接的最后十秒”落时”的网关 立即下载
低代码开发师(初级)实战教程 立即下载