gpt4 book ai didi

java - 对于数据报接收器来说,多少个线程比较合适?

转载 作者:行者123 更新时间:2023-12-02 05:20:06 27 4
gpt4 key购买 nike

我为我用 java(和 LWJGL)创建的游戏创建了一个发送-接收数据报系统。

但是,这些数据报经常被丢弃。这是因为服务器正在等待主循环中的各种 IO 操作和其他处理完成,同时新的数据报正在发送给它(它显然没有监听)。

为了解决这个问题,我在主线程中保留了捕获数据报的 while true 循环,但我不是在主线程中进行处理,而是分支到不同的线程中。

像这样:

ArrayList<RecieveThread> threads = new ArrayList<RecieveThread>();
public void run(){

while (true){
//System.out.println("Waiting!");
byte[] data = new byte[1024];
DatagramPacket packet = new DatagramPacket(data, data.length);
try {
socket.receive(packet);
} catch (IOException e) {
e.printStackTrace();
}



//System.out.println("Recieved!");
String str = new String(packet.getData());
str = str.trim();
if (threads.size() < 50){
RecieveThread thr = new RecieveThread();
thr.packet = packet;
thr.str = str;
threads.add(thr);
thr.start();
}else{
boolean taskProcessed = false;
for (RecieveThread thr : threads){
if (!thr.nextTask){
thr.packet = packet;
thr.str = str;
thr.nextTask = true;
taskProcessed = true;
break;
}
}
if (!taskProcessed){
System.out.println("[Warning] All threads full! Defaulting to main thread!");
process(str, packet);
}

}

}
}

这是为每个传入的数据报创建一个新线程,直到达到 50 个数据包,此时它选择在等待下一个任务的现有线程之一中进行处理 - 如果所有线程都在处理,则默认为主线程。

所以我的问题是:多少个线程比较合适?我不想让任何人的系统重载(同样的代码也会在玩家的客户端上运行),但我也不想增加系统丢包率。

另外,不同的线程是个好主意吗?有人有更好的方法吗?

编辑:这是我的 RecieveThread 类(类长 777 行):

    String str;
DatagramPacket packet;
boolean nextTask = true;
public void run(){
while (true){
////System.out.println("CLIENT: " + str);
//BeforeGame
while (!nextTask){
//Nothing
}
<Insert processing code here that you neither know about, nor care to know about, nor is relevant to the issue. Still, I pastebinned it below>
}
}

Full receiving code

最佳答案

首先,任何使用数据报(例如 UDP)进行通信的系统都必须能够应对丢失的请求。它们将会发生。您能做的最好的事情就是将典型掉落率降低到可以接受的程度。但您还需要认识到,如果您的应用程序无法处理丢失的数据报,那么它就不应该使用数据报。请改用常规套接字。

现在讨论要使用多少个线程的问题。答案是“这取决于情况”。

  • 一方面,如果没有足够的线程,可能会有未使用的硬件容量(核心),可以在高峰时间使用......但事实并非如此.

  • 如果一次运行(或可运行)的线程太多,它们将在不同级别上争夺资源:

    • CPU 竞争
    • 内存带宽的竞争
    • 锁和共享内存的争用。

    如果线程太多,所有这些因素(以及相关的二阶效应)都会降低吞吐量……相对于最佳吞吐量。

  • 如果您的请求处理涉及与其他计算机上的数据库或服务器通信,那么您需要足够的线程来允许在等待响应时发生其他事情。

根据经验,如果您的请求是独立的(共享数据的争用最少)并且完全位于内存中(没有数据库或外部服务请求),那么每个核心一个工作线程是一个很好的起点。但您需要准备好调整(也许重新调整)它。

最后,还有处理过载的问题。一方面,如果过载情况是暂时的,那么排队是一个合理的策略……前提是队列不会太深。另一方面,如果您预计过载会很常见,那么最好的策略是尽早放弃请求。

但是,还有一个次要问题。丢弃的请求可能需要客户端注意到它在给定时间内没有收到回复,然后重新发送请求。这可能会导致更严重的问题;即客户端在服务器实际丢弃请求之前重新发送请求...这可能导致同一请求被多次处理,并导致有效吞吐量灾难性下降。

请注意,如果您有太多线程并且它们由于资源争用而陷入困境,则可能会发生同样的情况。

关于java - 对于数据报接收器来说,多少个线程比较合适?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26578692/

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