2011-03-31 95 views
1

我有这个绝妙的想法来加速生成36个文件所需的时间:使用36个线程!不幸的是,如果我用36个线程/会话启动一个连接(一个连接对象),那么与一次执行每个线程相比,所有内容都会更多。
现在,如果我尝试创建36间新的连接(36个j2ssh连接对象),则每个线程拥有服务器的单独连接,无论我走出内存异常(不知何故程序仍然运行,并成功结束其工作,执行速度较慢当我执行一个接一个的线程时)。在java中运行多少个线程?

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

+0

您是否在服务器或j2ssh连接的客户端上运行您的工作线程? – 2011-03-31 12:54:26

+0

@PaŭloEbermann在服务器上运行它们,线程==向服务器发送2条命令 – user615927 2011-03-31 13:25:14

+0

听起来就像您需要查看JVM中是否内存不足。 – 2012-10-01 10:25:36

回答

10

你可以缩小它与ExecutorService更合理的线程数。您可能希望在可用的处理器内核数量附近使用某些东西,G:

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(); 
+0

那么你在这里看到的完成时间是〜30分钟我猜想36个操作中的每一个都是一个接一个地创建和执行的,thread1.start; thread1.end; thread2.start; thread2.end..thread36.end ... I个人预计在12分钟内至少不会超过30,它现在可以提高速度线程数(Executors.newFixedThreadPool(threads); )我设置了4 – user615927 2011-03-31 12:33:17

0

使用比机器上的内核数量多的线程只会减慢整个过程。它会加快,直到你达到这个数字。

+0

所以如果我有4个核心,我相信当时最佳的速度是使用3个线程?至少我已经检查过(使用几个命令)这样的时间:Executors.fixedThreadPool(2)-time 6:40min fixedThreadPool(3)-5:28min。 ThreadPool(4)-9:56分钟waylonger! ThreadPool(8)-13:13分钟。无法使用我可以使用的最大线程数是3?! – user615927 2011-03-31 13:06:13

1

蛮力:配置文件增量。逐渐增加线程数量并检查性能。至于连接的号码就是36,它应该是很容易

1

你需要明白,如果你创建36个线程你仍然有一个或两个处理器,它将大部分时间威胁之间进行切换。

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

0

确保您不会创建比您拥有处理单元更多的线程,或者您可能会创建更多的开销,而且上下文切换的开销将超过并发性。另外请记住,您只有1个硬盘驱动器和1个硬盘驱动器控制器,因此我怀疑多线程会在这里帮助您。

+0

**请记住,您只有1个硬盘驱动器和1个硬盘驱动器控制器,因此我怀疑多线程会在这里帮助您。**为什么?如果我可以通过腻子打开5个不同的窗口(5个连接到服务器),并执行5个命令组,我应该能够使用java做同样的事情?! – user615927 2011-03-31 13:00:37

+0

如果您要在一个系统上创建36个文件,或者您没有将36个文件连接到单个系统,那么驱动器并发性可能会成为一个问题,除非系统正在使用单个HDD以外的存储系统。你必须想象一个HDD是一个单线程实体,你一次只能写一个。 – Lazarus 2011-03-31 14:10:22

+0

您需要明白,线程之间的切换不是“免费”,这会花费时间。这只是一小段时间,但当你多次使用36个线程时,每次可能会多次切换上下文,并且该库可能没有针对多线程进行大量优化,您所看到的方式会比您想象的要多。线程不是万能的灵丹妙药,除非你真的明白发生了什么,我建议不要使用它,它就像一把非常锋利的刀。如果你不知道如何正确使用它,那么你将会伤害自己。 – Lazarus 2011-03-31 14:17:14

2

您的英特尔i5有两个内核;超线程使它们看起来像四个。所以你只能得到四个内核的并行化价值;其余的线程都是时间片。

假设每线程1MB RAM只是创建线程,然后添加每个线程都需要处理的文件的存储。这会给你一个关于你为什么会发生内存错误的想法。你正在处理的文件有多大?你可以看到,如果它们很大,同时将它们存储在内存中,你会遇到问题。

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

我倒是基准1个线程,然后增加他们,直到我发现,性能曲线变平。

+0

好吧,你是对的,serever可以同时进行至少三个命令(甚至可能是36)。所以我打算在thread1,2上同时运行两个命令,然后在主线程上运行第三个命令?! – user615927 2011-03-31 12:50:24

3

一个好的做法是产生相当于处理器内核数量的线程。我通常使用Executors.fixedThreadPool(numOfCores)执行者服务,并且继续为我的工作队列提供工作,这很简单。 :-)

1

一种调整方式线程机器的大小numebr是使用

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); 
1

首先,你必须找出瓶颈是

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

  • 如果是磁盘IO,创建多个线程写入(或读取)仅有助于访问不同的磁盘(这种情况很少)。但是当你在一个线程中等待磁盘IO时,你可以让另一个线程执行CPU绑定的事情。

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

+0

另一个注意事项:在unix-ish机器上,htop是一个很好的工具请参阅CPU和内存使用情况。 – trillions 2012-08-29 21:37:24