【问题标题】:Run multiple threads on the spot and wait for all to finish, convenience and safe hashMap现场运行多线程,等待全部完成,方便安全的hashMap
【发布时间】:2016-12-14 10:41:32
【问题描述】:

我刚开始学习线程背后的概念,但遇到了一个问题。

我有一个N Strings 数组,其中N 是可变的,但总是<= 5。 我还有另一个空数组,容量为N

现在,我必须对每个字符串 one by one 进行一些复杂的计算,并且每个结果都放入空数组中,与刚刚检查的字符串在同一索引上。

当一切都结束后,结果数组被分析并保留最长的结果。所有这一切发生的线程是主线程。

计算需要很长时间,所以我在考虑是否值得打开N 新线程,并一起评估所有线程。

值得一提,计算涉及查找HashMap<String, customObject> 上的字符串,这对所有字符串都是相同的。因此,使用线程,它们将一起访问它。他们不会编辑它,只是寻找值。地图可以更改,但在执行过程中永远不会更改,因为它会在代码中的其他部分发生更改,在主线程中。

示例:

//Current approach

HashMap<String, Object> m = new HashMap<>(); //filled with 10^6 values

String[] data = new String[3];
Object[] results = new String[3];

results[0] = complexCalculationsAndSearcOnHashMap(data[0]); 
results[1] = similarComplexCalculationsAndSearcOnHashMap(data[1]);
results[2] = otherComplexCalculationsAndSearcOnHashMap(data[2]);

//Now every complex calculation has to wait until the last one ended before starting. But the only thing that actually should have to wait is this next line:

Object finalResult = longest(results);

所以我的问题是,我应该构建 3 个线程并将复杂的计算放在 run 方法中吗?方便吗,还是我把整个线程概念弄错了?这在应用程序中造成了瓶颈,需要很长时间才能完成。

线程示例:

HashMap<String, Object> m = new HashMap<>(); //filled with 10^6 values

    String[] data = new String[3];
    Object[] results = new String[3];

    Thread t0 = new Thread(){

    public void run(){
      results[0] = complexCalculationsAndSearcOnHashMap(data[0]);
    }
};

//Thread t1, t2..
//t0.start(), t1.start()...

 Object finalResult = longest(results);

如果前面的答案是肯定的,我如何让最后一行等待所有 3 个线程完成,同时它们 彼此独立运行我是否通过循环将所有 3 个都加入它?

最后但同样重要的是,这样使用 HashMap 是否安全
或者我应该切换到另一个更适合线程的集合对象? 我已经阅读了一些关于此的想法,但似乎没有人同意。 会更慢吗? 除非目前非常必要,否则我不能失去任何优化。

编辑:

需要注意的是,“他们需要很长时间才能完成”不应该是理所当然的。虽然 97% 的时间 N 个函数确实需要很长时间才能完成,但它们可能几乎是瞬时完成的。 我不知道这是否有区别。

** 编辑 2:**

我不仅要问如何运行所有 4 个并等待它们完成,我还需要知道在这种情况下这样做是否正确,或者它是否不会改变任何事情,我还需要了解如果可以这样使用 hashMap。

** 代码详情 **

  • 所有这些都发生在同一个对象中,从未使用过静态字段。
  • HashMap 早已在另一个对象中初始化。
  • HashMap 可以更改,但在另一个对象中,在同一个线程上。所以它不会在其他 3 个线程运行时发生。
  • 这是应用程序唯一一次使用更多线程。

【问题讨论】:

  • 在副本上 - 描述如何使用 Futures 的答案是最干净的 IMO,但所有答案都为您提供了解决方案。
  • "...以这种方式使用 HashMap 是否安全?" - 这取决于您在哪里以及如何初始化地图。事实上,这其中的许多方面将取决于您的代码的精确细节。
  • 我不仅在问如何等待,我也在问这样做是否正确、是否值得,以及地图是否安全......
  • 哪些细节?我会提供给他们的。在所有这些代码发生之前很久就创建并初始化了地图。

标签: java arrays multithreading optimization


【解决方案1】:

您可以使用简单的方法并为您拥有的每个“计算”创建一个线程

    Thread[] workers = new Thread[count];
    for (int i = 0; i < count; i++) {
        final int index = i;
        //create thread to calculate i-th value
        workers[i] = new Thread(new Runnable() {
            @Override
            public void run() {
                results[index] = complexCalculationsAndSearcOnHashMap(data[index]);
            }
        });
        workers[i].start();
    }
    for (int i = 0; i < count; i++) {
        //wait until threads execution is finished
        workers[i].join();
    }

    //Test output
    System.out.println(Arrays.toString(results));

如果您的计算函数依赖于索引...您可以使用索引选择相应的函数或在循环外创建线程。

【讨论】:

  • 这样hashMap安全吗?
  • 只要在'计算'线程运行时不修改HashMap,使用是安全的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-06-10
  • 1970-01-01
  • 2014-09-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-01
相关资源
最近更新 更多