我正在开发一个 bittorrent 客户端。在与同行交流时,我与他们交流的最简单方法是为每个人生成一个新线程。但是,如果用户想与大量对等点保持连接,我会导致我产生大量线程。
我想到的另一种解决方案是让一个线程遍历对等对象并运行它们一段时间。
我主要在 ruby 中检查了其他库(我的是在 java 中),它们为每个新对等点生成一个线程。如果用户将连接数设置为 100 或 200 之类的高数字,您认为生成一个线程会降低性能吗?
我正在开发一个 bittorrent 客户端。在与同行交流时,我与他们交流的最简单方法是为每个人生成一个新线程。但是,如果用户想与大量对等点保持连接,我会导致我产生大量线程。
我想到的另一种解决方案是让一个线程遍历对等对象并运行它们一段时间。
我主要在 ruby 中检查了其他库(我的是在 java 中),它们为每个新对等点生成一个线程。如果用户将连接数设置为 100 或 200 之类的高数字,您认为生成一个线程会降低性能吗?
除非您运行数千个线程,否则这应该不是问题。我会考虑妥协,使用线程池。您可以在运行时检测 CPU 的数量,并据此决定启动多少线程,然后在线程池出现时将工作分配给线程池。
您可以通过使用非阻塞 IO (java.nio.*)完全避免该问题。
我建议使用 Executor 来保持池中的线程数。
Executors.newFixedThreadPool(numberOfThreads);
有了这个,您基本上可以将“任务”添加到池中,一旦线程可用,它们就会完成。这样,您就不会耗尽最终用户计算机的所有线程,同时仍然可以完成很多工作。如果您将其设置为 16,您将非常安全,尽管您始终可以允许用户更改此数字,如果他们愿意的话。
不.....
一旦我有同样的疑问并创建了一个具有 400 个线程的 .net 应用程序(4 年前)......
如果他们不做很多工作,用一台像样的机器你应该没问题...
对于大多数工作站级机器来说,几百个线程不是问题,而且编码更简单。
但是,如果你有兴趣追求你的想法,你可以使用Java 的 NIO 包提供的非阻塞 IO 特性。Jean-Francois Arcand 的博客包含许多从为 Glassfish 创建 Grizzly 连接器中学到的好技巧。
使用线程池,你应该安全地使用相当大的池大小(100 左右)。CPU 不会成为问题,因为您与这种类型的应用程序是 IO 绑定的。
您可以轻松地使池大小可配置并设置合理的最大值,以防止所有线程出现与内存相关的问题。当然,只有在实际使用所有线程时才会发生这种情况。
例如,在 32 位 Windows 中,实际上您可以创建的本机线程的最大数量(2 Gigs /(线程数 * ThreadStackSize(默认为 2MB))或类似的东西)。因此,如果连接太多,您可能会用完虚拟内存地址空间。我认为妥协可能会奏效:使用运行例如 10 个线程(取决于机器)的线程池并均匀分布连接。在线程内部循环通过分配给此线程的对等方。并限制最大连接数。