6
//    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;

我注意到无论专辑数量有多少,for each 循环总是需要更短的时间才能完成。我做错了吗?还是我需要一台具有多核的计算机。我对并行计算的整个概念真的很陌生,如果我的问题很愚蠢,请原谅我。

4

2 回答 2

6

在您的并行示例中,您为每一列提交一个任务。将任务加入队列的开销可能大于并行执行的好处。“任务”确实是一个快速的任务(将单个元素插入数组并返回),从而加剧了这种情况。实际上,Executor将每个接收到的任务添加到队列中(并且添加成本很高)。然后您将 N 个任务添加到队列中,每个任务都将一个元素添加到数组中。并发操作只执行后半部分

如果任务更复杂,您可以以“块”的形式提交工作(例如,如果您有 N 个元素和 P 个处理器,则每个块将有 N/P 个元素或 N/P+1 个元素)。该策略有助于减少开销。

另请注意,这ArrayList不是同步的,那么多个任务的并发执行可能会损坏您的列表。您可以使用并发集合来避免此问题,但第一个观察结果仍然存在。

于 2013-03-17T08:34:35.480 回答
-1

这是一个不好的做法,创建线程所消耗的时间和 cpu 比你的线程正在做的要多得多:albumIds2.add(column.getName());

于 2013-03-17T08:37:43.470 回答