0

I just started learning the concept behind threads and I'm stuck on a problem.

I have an array of N Strings, with N being variable but always <= 5. I have another empty array, of capacity N.

Now, I have to make some complex calculations on each string, one by one, and each result goes in the empty array, on the same index as the string that just got checked.

When everything has ended, the result array is analyzed and the longest result is kept. The thread where all of this is happening is the main-thread.

The calculations take a lot of time, so I was thinking if it might be worth it to open N new threads, and evaluate all of them together.

It's worth mentioning that the calculations involve looking up the strings on a HashMap<String, customObject>, which is the same one for all of them. So with threads, they will access it together. They will not edit it, just look for values. The map can change, but never while this is executing, because it changes from other parts later in the code, in the main thread.

Example:

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

So my question is, should I build 3 threads and put the complex calculations in the run method? Is it convenient, or have I gotten the whole thread concept wrong? This is creating a bottleneck in the application, it takes too long to finish.

Example with threads:

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);

IF the previous answer is yes, how do I get the last line to wait for all 3 threads to finish, while they run independently of eachother ? Do I join it with all 3 with a loop?

Last but not least, is it safe to use the HashMap that way ?
Or should I switch to another collection object that works better with threads? I have read several thoughts on this and nobody seems to agree. Would it be slower? I cannot lose any optimization unless extremely necessary at the moment.

Edit:

It should be noted that the "they take a long time to finish" should not be taken for granted. While 97% of the time the N functions do take a long time each to finish, it can happen that they are almost instantaneous. I do not know if this makes a difference.

** EDIT 2: **

Not only am I asking how to run all 4 and wait for them to finish, I also need to know if it's the right thing to do in this case or if it won't change a thing, ALSO I need to understand if it's ok to use the hashMap that way.

** DETAILS ON THE CODE **

  • All of this happens within the same object, no static fields are ever used.
  • The HashMap has already been initialized, long before, in another object.
  • The HashMap can change, but in another object, on the same thread. So it can't happen while the other 3 threads run.
  • This is the only time the application uses more threads.
Lory A
  • 520
  • 1
  • 5
  • 17
  • Possible duplicate of [How to wait for all threads to finish, using ExecutorService?](http://stackoverflow.com/questions/1250643/how-to-wait-for-all-threads-to-finish-using-executorservice) – Erwin Bolwidt Dec 14 '16 at 00:51
  • On the duplicate - the answer that describes how to use `Future`s is the cleanest IMO, but all the answers provide a solution for you. – Erwin Bolwidt Dec 14 '16 at 00:52
  • *"... is it safe to use the HashMap that way ?"* - That depends on where and how you initialize the map. In fact, many aspects of this will depend on the precise details of your code. – Stephen C Dec 14 '16 at 00:59
  • I am not only asking how to wait, I'm also asking if it's the right thing to do, if it's worh it, and if it's safe with the map.. – Lory A Dec 14 '16 at 00:59
  • Which details? I'll provide them. The map is created and initialized long before all of this code happens. – Lory A Dec 14 '16 at 01:00
  • If you have that many questions, you should create separate questions on SO, otherwise it would be closed for being too broad and requiring too lengthy answers. – Erwin Bolwidt Dec 14 '16 at 01:09
  • Since they are all very on point an connected, I saw creating too many questions to be more spammy. Example answer could be: Yes, it makes more sense to use threads there and provided these conditions, the hashMap can be safely used. Or.. No you got it all wrong. While there are several points to the questions, the answers need only be a few lines, not very broad. – Lory A Dec 14 '16 at 01:12

1 Answers1

3

You may use straightforward approach and create a Thread for every 'calculation' you have

    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));

In case your calculation function depends on index ... you may choose corresponding functions using index or create your Threads outside loop.

Anton Dovzhenko
  • 2,399
  • 11
  • 16