// parallel processing
int processors = Runtime.getRuntime().availableProcessors();
ExecutorService executorService = Executors.newFixedThreadPool(threads);
final List<String> albumIds2 = new ArrayList<String>();
long start2 = System.nanoTime();
for (final HColumn<String, String> column : result.get().getColumns()) {
Runnable worker = new Runnable() {
@Override
public void run() {
albumIds2.add(column.getName());
}
};
executorService.execute(worker);
}
long timeTaken2 = System.nanoTime() - start2;
我有类似上面示例的代码,它会创建List<String>
专辑ID。
该列是来自cassandra数据库的切片。
我记录了要创建的整个专辑列表所花费的时间。
我使用增强的for循环完成了同样的操作。
QueryResult<ColumnSlice<String, String>> result = CassandraDAO.getRowColumns(AlbumIds_CF, customerId);
long start = System.nanoTime();
for (HColumn<String, String> column : result.get().getColumns()) {
albumIds.add(column.getName());
}
long timeTaken = System.nanoTime() - start;
我注意到无论专辑的数量有多大,每个循环总是花费更短的时间来完成。我做错了吗?或者我需要一台具有多个核心的计算机。我对并行计算的整个概念都很陌生,如果我的问题很愚蠢,请原谅我。
答案 0 :(得分:6)
在您的并行示例中,您要为每列提交一个任务。排队任务的开销可能大于并行执行的好处。 “任务”实际上是一个快速的(将一个元素插入一个数组并返回)会加剧这种情况。实际上,Executor
会将每个收到的任务添加到队列中( 添加成本很高)。然后,您将N任务添加到队列,每个任务都向该数组添加一个元素。并发操作仅执行后一部分
如果任务更复杂,您可以以“块”的形式提交作品(例如,如果您有N个元素和P个处理器,则每个块将具有N / P元素或N / P + 1个元素)。该策略有助于减少开销。
另请注意ArrayList
未同步,然后并发执行多个任务可能会损坏您的列表。您可以使用并发集合来避免此问题,但第一个观察仍然存在。
答案 1 :(得分:-1)
这是一个不好的做法,创建线程所消耗的时间和CPU远远超过你的线程所做的事情:albumIds2.add(column.getName());