因此,我有一个循环,在其中我创建了数千个线程来处理我的数据。
我检查了一下,存储一个线程会减慢我的应用程序的速度。
它来自我的循环:
Record r = new Record(id, data, outPath, debug);
//r.start();
threads.add(r);
//id is 4 digits
//data is something like 500 chars long
它会让我的for循环停止一段时间(一次跑步需要一秒钟或更长时间,太多了!)。
仅初始化>持续时间:0:00:06.369
将线程添加到ArrayList>持续时间:0:00:07.348
问题:
- 存储线程的最佳方式是什么
- 如何使线程更快
- 我应该创建线程并用特殊的执行器运行它们吗?例如,一次运行10个线程,然后再运行10个等等。?(如果是,那么怎么做?)
考虑一下,拥有非常多的线程并不是很有用。
至少你可以同时执行相当于cpu核心数量的线程。
最好的方法是重用现有线程。要做到这一点,您可以使用Executor框架。
例如,要创建一个内部最多处理10个线程的Executor,您可以执行以下操作:
List<Record> records = ...;
ExecutorService executor = Executors.newFixedThreadPool(10);
for (Record r : records) {
executor.submit(r);
}
// At the end stop the executor
executor.shutdown();
使用与此类似的代码,您还可以提交数千个命令(可运行的实现),但创建的线程不超过10个。
我猜真正让你慢下来的不是.add方法。我的猜测是,数百个线程并行运行才是真正的问题所在。当然,像"add"这样的简单命令将在管道中排队,并且可能需要很长时间才能执行,即使执行本身很快。此外,您的数据结构可能有一个位于O(n)中的add方法。
可能的解决方案:*找到一个真正的免费解决方案。例如,对线程进行优先级排序。*在执行之前,将它们全部添加到您的数据结构中
虽然可以这样工作,但强烈建议不要为这样的东西创建更多的线程。正如David Lorenzo已经指出的那样,您应该使用线程执行器。
我有一个循环,我在其中创建了数千个线程。。。
这是个坏兆头。创建线程的成本很高。
假设您的程序创建了数千个线程,因为它有数千个任务要执行。诀窍是,将线程与任务解耦。只创建几个线程,然后重用它们。
这就是线程池为您所做的。
了解java.util.concurrent.ThreadPoolExecutor
类和相关类(例如Future
)。它实现了一个线程池,很可能它提供了您需要的所有功能。
如果您的需求足够简单,您可以使用java.util.concurrent.Executors
中的一种静态方法来创建和配置线程池。(例如,Executors.newFixedThreadPool(N)
将创建一个新的线程池,其中正好有N个线程。)
如果你的任务都是计算绑定的,那么没有理由拥有比机器中CPU数量更多的线程。如果您的任务花费时间等待(例如,等待来自网络客户端的命令),那么创建多少线程的决定将变得更加复杂:这取决于这些线程使用了多少资源。你可能需要试验才能找到正确的数字。