我有个绝妙的想法,可以加快生成36个文件所需的时间:使用36个线程!但是,如果我使用一个连接(一个连接对象)和36个线程/会话启动一个连接,一切都比逐个执行每个线程要慢得多。现在,如果我尝试创建36个新连接(36个连接对象),那么每个线程都有一个单独的连接到服务器,要么出现内存不足异常(某种方式程序仍在运行,并成功结束其工作,比逐个执行每个线程时慢)。那么该怎么办?如何找到最佳的线程数?因为在启动我的36个线程之前,是3?我正在使用联想笔记本电脑Intel Core 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)
执行服务,并从我的作业队列中不断提供任务,非常简单。 :-)
将线程数量调整到机器大小的一种方法是使用
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);
使用比机器核心数更多的线程会减慢整个过程的速度。只有达到这个数量之后,才会加速。
暴力破解:逐步调整配置文件。逐渐增加线程数并检查性能。由于连接数仅为36,因此应该很容易。
你需要明白的是,如果你创建了36个线程,但你仍然只有一到两个处理器,这将会大部分时间在不同的线程之间进行切换。
我建议你先把线程数适当增加一些,比如说6个,看看它们的运行情况,然后再继续调整。
首先你必须找出瓶颈在哪里。
如果是SSH连接,通常并行打开多个连接没有帮助。最好使用一个连接上的多个通道(如果需要)。
如果是磁盘IO,创建多个线程写入(或读取)只有在它们访问不同磁盘时才有帮助(这种情况很少见)。但是,当您在一个线程中等待磁盘IO时,您可以有另一个线程执行CPU密集型任务。
如果是CPU,并且您有足够的空闲核心,则更多的线程可以提高性能。如果它们不需要访问共享数据,甚至可以更多。但是,比核心数多的线程(+一些执行IO的线程)并没有帮助。(还要考虑通常还有其他进程在服务器上运行。)
请确保您不要创建比处理单元更多的线程,否则您可能会因上下文切换而产生更多的开销,而不是获得并发性所带来的好处。同时,请记住您只有1个硬盘和1个硬盘控制器,因此我怀疑多线程在这里并没有什么帮助。