我正在开发一个Andoid应用程序,它由在后台运行的服务和连接到该服务的一些活动组成。服务运行在它自己的进程上。
我的服务主要有3个类:ServiceMain,ServiceWorker,Message。
ServiceMain具有活动使用的所有功能,如logIn,logOut,send ...等。
消息表示发送到我们的服务器或收到的消息。只需一个String和一个bool,其中String是消息,bool是一个标志,表示是否需要来自服务器的响应。
ServiceWorker是Thread的子类,它使用套接字完成所有发送消息的接收。
ServiceMain包含2个队列:
Queue<Message> Sendingqueue= new ConcurrentLinkedQueue<Message>();
Queue<Message> Recievequeue = new ConcurrentLinkedQueue<Message>();
如果调用了logIn方法,则会创建并启动ServiceWorker。在它的构造函数中,它获取对两个队列的引用并保留它们。
private final Queue<Message> Sendingqueue;
private final Queue<Message> Recievequeue;
ServiceMain然后创建一些消息(例如M1,M2)并将它们添加到Sendingqueue。
ServiceWorker建立与我们服务器的连接,然后运行到一个循环中,它在Sendingqueue中查找消息,发送它们并做一些其他事情,如接收......
希望现在情况很清楚。
在ServiceWorker中,Sendingqueue发生了一些奇怪的事情:
假设ServiceMain将两条消息M1和M2添加到Sendingqueue,而ServiceWorker正在做一些耗时或未连接到我们服务器的消息。 Sendingqueue现在包含两条消息。
如果ServiceWorker下次获得队列的长度,则会看到2个项目。好到目前为止。 然后它会在Sendingqueue上调用peek()(只有在成功发送时才会删除该消息)并且应该获取M1,因为它是先添加的。 但它获得了M2。 Sendingqueue似乎已被还原。
这里出了什么问题?我该怎么做才能避免这种情况?
感谢您的任何建设性回复。
德特勒夫
答案 0 :(得分:0)
ConcurrentLinkedQueue不对订单做任何保证,但如果你要添加到结尾并从开始采取(反之亦然),则元素的顺序不应该改变。如果您从开头或结尾添加和删除,可能会遇到问题,因为这意味着您每次都要处理最新而不是最旧的。
如果你有一个功能强大的服务器,我仍然会建议这种做法有点过分。我没有使用后台线程来执行处理,而是使用主线程。
注意:套接字已经是客户端和服务器上的输入和输出队列,因此在大型系统中添加第三层排队可能是多余的,而在较小的设备中则是低效的。