Java 处理许多传入数据包的最佳方法

Java 处理许多传入数据包的最佳方法,java,multithreading,sockets,Java,Multithreading,Sockets,我目前正在开发一个简单的P2P网络作为练习。网络中的每个节点向其他节点的子集发送心跳,以便能够检测已离开网络的节点。除了心跳数据包,当新节点加入/离开网络时,当它们想要定位资源(小文本文件)时,我发送数据包。所有数据包都是UDP数据包 每当我收到一个数据包,我就会启动一个新的线程来处理这个特定的数据包。然而,我关心的是我在一个应用程序生命周期中启动的线程数量,这相当多(特别是因为心跳)。(还有死锁的风险以及我希望避免的类似情况) 我考虑使用一个队列或类似的东西,在那里我放置所有传入的数据包,并使

我目前正在开发一个简单的P2P网络作为练习。网络中的每个节点向其他节点的子集发送心跳,以便能够检测已离开网络的节点。除了心跳数据包,当新节点加入/离开网络时,当它们想要定位资源(小文本文件)时,我发送数据包。所有数据包都是UDP数据包

每当我收到一个数据包,我就会启动一个新的线程来处理这个特定的数据包。然而,我关心的是我在一个应用程序生命周期中启动的线程数量,这相当多(特别是因为心跳)。(还有死锁的风险以及我希望避免的类似情况)

我考虑使用一个队列或类似的东西,在那里我放置所有传入的数据包,并使用一个线程处理来自该队列的所有数据包(类似于生产者-消费者模式)。我想快速处理数据包,这样发送者就不会认为数据包丢失了


处理大量不同传入数据包而不必为每个数据包启动新线程的最佳方法是什么?我应该使用我所拥有的、生产者消费的还是其他东西?

您的应用程序处理一个数据包需要多长时间

对于ping线程,在接收到它们时处理它们可能更快,您可以将其他线程放入共享数据结构中,例如特定的阻塞队列,因此当队列为空时,工作线程等待新作业,当添加新作业时,线程被唤醒并将执行该作业

可能每个包启动一个线程会使您在启动和停止线程时比实际执行任务时花费更多的时间

如果响应一个数据包所做的事情对于所有类型的数据包来说都不是那么耗时,那么可能是由于队列锁和调度线程所花费的额外时间使程序变慢而不是变快


在任何情况下,使用线程池并在开始时启动辅助线程。如果需要,可以根据过去几分钟的负载动态增加或减少工作线程的数量。

我将使用
事件驱动体系结构。为每个数据包创建一个新线程是不可伸缩的,因此这将在一定的工作量下工作,但有一点它将不再工作。您可以将其与Facebook聊天等聊天程序进行比较,其中消息是数据包。
事件驱动的体系结构将是可伸缩的,并且完全符合您的需求。只需在谷歌上搜索一下,就可以找到许多编程语言的库,所以只需为您选择合适的库(我喜欢在Erlang、Scala、C或Python中这样做)

编辑:好的,没有看到java标记。但语言并不重要

以该链接为例:


我发现了解事件驱动编程的概念是一个很好的方法。

当然。将生产者消费者与LinkedList一起使用。我能想到的最简单的方法。你可以从一些老式的方法开始,比如你提到的你自己的方法,做一些基准测试,然后尝试一些最新的方法,比如“Disruptor”(),然后再做一些基准测试。这可能有助于量化“许多不同的传入数据包”。。。相对而言,心跳应该不会太多,因为现代系统通常可以根据NIC的数量和类型每秒处理数百到数千个数据包。我怀疑心跳可能在每分钟几十次的范围内……
java.nio.Selector
可能会满足您的需要。@twalberg您的心跳是对的;)。现在我每分钟发送30次心跳。发送所有其他消息的时间取决于用户的操作(离开、定位、加入),但当我现在进行测试时,总的来说,我并没有超过每分钟50-60个数据包。时间略有不同。大多数数据包处理速度很快,但有些操作涉及发送新数据包并期望得到响应。但我想我会选择线程池和队列。谢谢。但是他使用的是UDP,所以他可能只有一个文件描述符。这并不排除使其异步的可能性。寻找非阻塞套接字、异步i/o甚至事件驱动套接字(基本上描述了所有相同的想法)。我知道仍然可以这样做,但我不确定在这种特定情况下值得这么做。