在java中运行多少个线程?

我有这个绝妙的主意,可以加快生成36个文件所需的时间:使用36个线程! 不幸的是,如果我用36个线程/会话启动一个连接(一个j2ssh连接对象),那么一切都比我一次执行每个线程要多得多。
现在,如果我尝试创建36个新连接(36个j2ssh连接对象),那么每个线程都有一个单独的连接到服务器,要么我的内存exception(不知何故程序仍然运行,并成功结束其工作,慢于时间我一个接一个地执行一个线程)。

那么该怎么办? 如何找到我应该使用的最佳线程数? 因为在开始我的36个线程之前Thread.activeCount()是3? 我正在使用联想笔记本电脑英特尔酷睿i5。

您可以使用ExecutorService将其缩小到更合理的线程数。 您可能希望使用接近可用处理器核心数量的东西,例如:

 int threads = Runtime.getRuntime().availableProcessors(); ExecutorService service = Executors.newFixedThreadPool(threads); for (int i = 0; i < 36; i++) { service.execute(new Runnable() { public void run() { // do what you need per file here } }); } service.shutdown(); 

一个好的做法是生成相当于处理器内核数量的线程。 我通常使用Executors.fixedThreadPool(numOfCores)执行器服务并继续从我的作业队列中提取作业,这很简单。 🙂

您的Intel i5有两个内核; 超线程使它们看起来像四个。 因此,您只能获得四个核心的并行化; 你的其余线程都是时间切片。

假设每个线程只有1MB RAM用于创建线程,然后添加每个线程处理文件所需的内存。 这将让您了解为什么会出现内存不足错误。 你正在处理的文件有多大? 您可以看到,如果它们非常大,同时将它们存储在内存中,您将遇到问题。

我假设接收文件的服务器可以接受多个连接,因此尝试这个有价值。

我用1个线程进行基准测试,然后增加它们,直到我发现性能曲线变平。

暴力:逐步增加轮廓。 逐渐增加线程数并检查性能。 由于连接数仅为36,因此应该很容易

您需要了解,如果您创建36个线程,您仍然拥有一个或两个处理器,并且它将在大多数情况下在威胁之间切换。

我会说你稍微增加一些线程,让我们说6并看看行为。 然后从那里开始

将线程数量调整到机器大小的一种方法是使用

 int processors = Runtime.getRuntime().availableProcessors(); int threads = processors * N; // N could 1, 2 or more depending on what you are doing. ExecutorService es = Executors.newFixedThreadPool(threads); 

首先, 你必须找出瓶颈的位置

  • 如果是SSH连接,则通常无法并行打开多个连接。 如果需要,最好在一个连接上使用多个通道。

  • 如果它是磁盘IO,则创建多个线程写入(或读取)只有在访问不同磁盘时才会有所帮助(这种情况很少见)。 但是,当您在一个线程中等待磁盘IO时,您可以让另一个线程执行CPU绑定的操作。

  • 如果它是CPU,并且您有足够的空闲内核,则更multithreading可以提供帮助。 更重要的是,如果他们不需要访问公共数据。 但是,更多的线程比核心(+一些线程做IO)没有帮助。 (另请注意,您的服务器上通常还有其他进程。)

使用比计算机内核数量更多的线程只会减慢整个过程的速度。 它会加速,直到你达到这个数字。

确保您没有创建比处理单元更多的线程,或者您可能会在上下文切换时创建比并发更多的开销。 还要记住,你只有1个硬盘和1个硬盘控制器,我怀疑multithreading会在这里帮助你。