1

我正在开发一个独立的 java 应用程序,它通过网络从大约 1000 个测量设备收集数据并将数据保存到数据库中。由于设备输出和/或网络速度较慢,每个设备的数据收集可能需要几分钟时间。数据收集必须在某个时间窗口内进行,所以我需要并行工作。

我的方法是为每个测量设备创建一个线程,将数据放入队列中,并在队列的另一端有一个或多个其他线程转换并保存数据。

这是一种可行的方法吗?现代机器是否能够处理那么多线程和网络连接?这是多么可扩展,在什么时候我需要在多台机器上工作?

如果您能就您推荐的并发类(即哪种队列、ThreadPoolExecutor 等——我还没有使用 java.util.concurrent,书在邮件中)给我指点,我也将不胜感激。

有没有更好的方法?

更新:

感谢您到目前为止的回答,这里是你们中的一些人要求的更多信息。

我从设备收到的数据是小于 1kb 的文件形式。我有可能在一次传输期间获得类似 25.000 个文件,尽管通常要少得多。

数据转换不是 cpu 密集型的,基本上是解析文件并将其转换为 java 数据类型(文件包含 c 数据类型,如 unsigned char 和 unix 时间戳),加上 CRC 计算。我创建了一个对象,其中包含一个文件的内容,我使用 JPA 将其保存到数据库中(我想我也可以在这种情况下使用纯 JDBC)。测量文件中没有顺序,因为它们包含设备序列号和时间戳。

稍后,当满足某些条件时,我将不得不添加某种警报,但这也不应该是 CPU 密集型的。

从到目前为止的答案中,我收集到网络连接和线程数应该不是问题。

我唯一想知道的是关于队列的方法。另一种方法是让数据收集线程也调用 DAO 方法来保存文件。我想我无论如何都必须使 DAO 线程安全,但我认为一些线程也可以完成这项工作,因为大部分时间将用于传输网络数据。

我还将研究异步 I/O 和一些提供它的框架。

再次感谢,稍后我会选择一个答案,也许我会得到更多的输入:)

4

3 回答 3

1

对于现代操作系统和硬件,处理 1000 多个更改线程和网络连接应该不是问题。真正的问题是您收集了多少数据,以及转换的复杂程度——这可能会决定一台机器可以处理多少。

于 2012-05-31T09:50:11.343 回答
1

假设您在 64 位 Linux、Oracle jdk 上运行(在这样的平台上默认 threadstacksize 为 1Mb),使用默认设置,您最终将使用大约 1Gb 的内存用于线程堆栈。我认为对于 OpenJDK 来说是一样的。不计算 os 分配的缓冲区。. .

如果这对你的要求来说太多了,你可能想看看http://netty.io。该框架在后台使用 java nio(可以配置为使用 bio,顺便说一句)。这样,您只需要少数线程来执行实际的 io(对给定的 tcp 连接执行读/写操作)。然后应将您的业务逻辑(更新数据库,计算一些测量值)卸载到单独的线程池中。Netty 也包括对此的支持。

如果您想为每个连接(每个测量设备?)使用 1 个线程,那么让另一组线程执行实际业务工作可能没有任何好处。我假设每个设备一个线程,因为您说设备可能很慢和/或网络可能很慢。如果您使用多个线程,则不会消除两个瓶颈(网络和设备)(可以预期相反)。

一般并发类:java.util.concurrent.* 是的,都竖起大拇指

于 2012-05-31T10:15:52.667 回答
0

IMO,您应该考虑使用异步 IO 从设备收集数据。一旦您从套接字读取了某些内容,将其发布到队列(并发或其他方式),并有一个线程池从该队列中读取项目。

唯一的复杂性是以设备的自然顺序维护数据,也许您可​​以为每个设备设置一个队列,并将某种令牌发布到线程池连接到的队列中,以指示哪个设备已准备好进行处理。然后一个线程将处理设备的队列并做必要的工作,如果它需要更多的数据,它不必从设备队列中消费,它可以把它留在那里,直到所有的数据都到达。

于 2012-05-31T10:15:40.647 回答