gpt4 book ai didi

java - 处理 Java 套接字并发

转载 作者:行者123 更新时间:2023-12-01 22:09:50 25 4
gpt4 key购买 nike

我正在构建一个服务器,该服务器每 2 秒通过一个 TCP 套接字在单独的线程上为每个用户发送数据。有时还会与常规数据一起发送特殊事件。有时,多个数据包中的数据会混合在一起,因此我创建了一个队列以确保它不会发生。但是问题依然存在,是我的方法不对还是我的代码有问题?

    protected void sendData (byte[] data) {
if (isSendingData) {
dataQueue.add(data);
return;
}

isSendingData = true;
Thread sendThread = new Thread() {
public void run () {
try {
BufferedOutputStream outStream = new BufferedOutputStream(connectionSocket.getOutputStream());
outStream.write(data);
outStream.flush();

// check queue, if there are data, send
byte[] moreData = null;
if (dataQueue.size() > 0) {
moreData = dataQueue.remove(0);
}
isSendingData = false;
if (moreData != null) {
sendData(moreData);
}
}
catch (Exception e) {
System.out.println ("Error sending data to peripheral: " + e);
isSendingData = false;
}
}
};

sendThread.start ();
}

最佳答案

使用队列消除并发问题的正确习惯是让一个长期存在的线程运行一个无限循环,从队列中获取元素并处理它们。通常,您将使用阻塞队列,以便在每次迭代时线程进入 hibernate 状态,直到有项目需要处理。

您的解决方案在许多方面与上述方案不同。例如:

    if (isSendingData) {
dataQueue.add(data);
return;
}

isSendingData = true;

- 如果同时调用此方法,这将导致竞争条件:两个线程都可以将 isSendingData 读取为 false,然后同时继续通过网络发送数据。如果 isSendingData 不是 volatile ,那么您还会遇到数据竞争(完全独立于上面解释的竞争条件)。

                if (dataQueue.size() > 0) {
moreData = dataQueue.remove(0);
}

——这是另一个竞争条件:在您读取大小为零后,另一个线程可以将项目添加到队列中。现在该项目可能永远不会被处理。它将在队列中徘徊,直到启动另一个此类线程。

您的解决方案不正确的更明显的方式是您启动的线程没有循环,并且旨在仅处理一条消息,以及队列中可能的一条额外消息。应该对此进行修改,以便不存在特殊情况,并且 sendData 始终无条件地提交到队列,并且永远不会自行发送任何数据。

关于java - 处理 Java 套接字并发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32032623/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com