在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会在这里帮助你。