我正在开发由在后台运行的服务和与该服务相关的一些活动组成的Andoid应用。服务在其自己的流程上运行。

我的服务主要有3个类:ServiceMain,ServiceWorker,Message。

ServiceMain具有活动使用的所有功能,例如logIn,logOut,send ...等。

邮件代表发送到我们的服务器或已收到的邮件。只是一个String和一个bool,其中String是消息,而bool是一个标志,指示是否需要服务器响应。

ServiceWorker是Thread的子类,并使用Sockets完成所有消息的接收。

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在ServiceWorker耗时或未连接到我们的服务器时向Sendingqueue添加了两条消息M1和M2。
现在,发送队列包含两个消息。

如果ServiceWorker下次获得队列的长度,它将看到2个项目。好的,到目前为止。
然后,它在Sendingqueue上调用peek()(仅在成功发送消息后才将其删除),并且应该得到M1,因为它是首先添加的。
但是得到M2。
Sendingqueue似乎已还原。

这是怎么了?我该怎么做才能避免这种情况?

感谢您的建设性答复。

德特尔夫

最佳答案

ConcurrentLinkedQueue不能保证顺序,但如果要添加到末尾并从头开始(反之亦然),则元素的顺序不应更改(反之亦然)。如果从头或尾添加和删除,可能会遇到问题,因为这将意味着您每次都在处理最新的而不是最旧的。

如果您拥有大型功能强大的服务器,我仍然建议这种方法过大。我将使用主线程来代替后台线程来执行处理。

注意:套接字已经是客户端和服务器上的输入和输出队列,因此在大型系统中添加第三层排队可能是多余的,而在较小的设备中则效率低下。

10-04 12:46