0

Below is a simple code only trying to use the same executorService for a type of string, which is not solving my problem of processing multiple strings together unless they are of the same type, in case they are of the same type the thread must wait for the previous string to be processed.
Also, please suggest if I can make use of blocking queue to implement this, and how?

Another approach I could think of, but not able to implement - Put all threads that have picked one type to wait in a queue, so they get processed sequentially. Meanwhile other types are picked up by other threads.

Type A <-Thread1<-Thread2<-Thread3<-Thread8
Type B <-Thread4<-Thread5
Type C <-Thread9... and so on.

import java.util.HashMap;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class SOS {
    volatile static int i = 0;

    public static void main(String[] args) throws InterruptedException, ExecutionException {
        ExecutorService executorService1 = Executors.newSingleThreadExecutor();
        ExecutorService executorService2 = Executors.newSingleThreadExecutor();
        ExecutorService executorService3 = Executors.newSingleThreadExecutor();
        ExecutorService[] e = {executorService1, executorService2, executorService3};
        String[] FeedList = {"A", "A", "A", "B", "B", "C", "C", "A", "C", "C", "C", "B", "B", "A", "A", "B", "B", "A",
            "A", "C"};



        final long startTime = System.currentTimeMillis();
        int k = 0;
        while (i < FeedList.length) {
            Callable<String> callable = new MyTask(FeedList, i);

            k = hash(FeedList, i, new RandomGen().Types());

            Future<String> success = e[k].submit(callable);
            if (!success.get().contains("Success"))
                System.out.println("Failure");
            i++;

        }

        e[0].shutdown();
        e[1].shutdown();
        e[2].shutdown();
        final long endTime = System.currentTimeMillis();
        System.out.println("Total execution time: " + (endTime - startTime));
    }

    private static int hash(String[] FeedList, int n, int numOfType) throws InterruptedException {

        HashMap<String, Integer> h = new HashMap<String, Integer>();
        int k = 0;

        for (int i = 0; i < FeedList.length; i++) {
            if (!h.containsKey(FeedList[i])) {
                k++;
                if (k >= numOfType)
                    k = 0;
                h.put(FeedList[i], k);

            }
            if (h.containsKey(FeedList[i]))
                Thread.sleep(1);

        }

        return h.get(FeedList[n]);
    }
}
  • Just to check I did get your requirement: All instances of a type need to be processed sequentially? So, there only can be as much concurrent activity as there are different types? – rpy Jun 02 '16 at 14:22

1 Answers1

0

You are calling get right after submitting, which waits for the execution to finish. That means that the executors will not be executing in parallel.

You should make all the Futures<...>s first, and than call get afterwards:

List<Future<String>> list = new ArrayList<>();

while (i < FeedList.length) {
    Callable<String> callable = new MyTask(FeedList, i);

    k = hash(FeedList, i, new RandomGen().Types());

    Future<String> success = e[k].submit(callable);
    list.add(success);            

    i++;    
}

for(Future<String> f : list) {
    if (!f.get().contains("Success"))
        System.out.println("Failure");
}

I also don't see the point in making i volatile, since it only gets accessed from one thread. It gets copied, when passing it to MyTask's constructor.

Jorn Vernee
  • 31,735
  • 4
  • 76
  • 93
  • This code is far from the solution I am looking for, but thanks for correcting me. :) Also, looking at the output, this fix works I am not sure. – user3055952 Jun 03 '16 at 09:55
  • @user3055952 I had to replace ```hash``` with another method since I don't know about ```RandomGen```. I made a method that simply returned an ```int``` based on if the string was "A", "B", or "C". I don't know how you're testing the results, but using ```System.currentTimeMillis``` is know to give inconsistent results, see: [How do I write a correct micro-benchmark in Java?](http://stackoverflow.com/questions/504103/how-do-i-write-a-correct-micro-benchmark-in-java). Lastly, a data set this small, might not be enough to amortize the cost of going parrallel. – Jorn Vernee Jun 03 '16 at 10:40