所以,我有一个循环,我创建了数千个处理我的数据的线程。
我检查并存储了一个线程会减慢我的应用。
这是我的循环:
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循环(一次运行需要一秒或更长时间,太多了!)。
仅限init>持续时间:0:00:06.369
将线程添加到ArrayList>持续时间:0:00:07.348
问题:
答案 0 :(得分:7)
考虑拥有一些非常高的线程并不是很有用。
至少你可以同时执行多个线程等于你的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();
使用与此类似的代码,您还可以提交数千个命令(Runnable实现),但不会创建超过10个线程。
答案 1 :(得分:0)
我猜这不是.add方法真的让你失望。我的猜测是,数百个并行运行的线程才是真正的问题。当然是一个简单的命令,如&#34;添加&#34;将在流水线中排队并且可能需要很长时间才能执行,即使执行本身很快。您的数据结构也可能具有O(n)中的add方法。
可能的解决方案: *找到一个真正的等待解决方案。例如。优先考虑线程。 *在执行之前将它们全部添加到数据结构中
虽然可以像这样工作,但强烈建议不要为这样的东西创建一些以上的线程。你应该像David Lorenzo已经指出的那样使用Thread Executor。
答案 2 :(得分:0)
我有一个循环,我创建了数千个线程......
那是一个不好的迹象。创建线程很昂贵。
假设您的程序创建了数千个线程,因为它需要执行数千个任务。诀窍是,将线程与任务分离。只创建几个线程,然后重复使用它们。
这就是线程池为您所做的。
了解java.util.concurrent.ThreadPoolExecutor
课程及相关课程(例如Future
)。它实现了一个线程池,很有可能它提供了你需要的所有功能。
如果您的需求足够简单,可以使用java.util.concurrent.Executors
中的一个静态方法来创建和配置线程池。 (例如,Executors.newFixedThreadPool(N)
将创建一个新的线程池,其中包含 N 个线程。)
如果您的任务都是计算绑定的,那么没有理由拥有比计算机中的CPU数量更多的线程。如果您的任务花费时间等待某些事情(例如,等待来自网络客户端的命令),那么创建多少线程的决定变得更加复杂:它取决于这些线程的资源量使用。您可能需要尝试找到正确的数字。