Lolly
Lolly

Reputation: 36372

Java: Using ExecutorService for concurrency

I want to execute some tasks parallel so I was searching for multithreading in Java and I found this class, ExecutorService. I tried with simple example but I am not sure whether it is running in parallel.

long startTime = System.currentTimeMillis();
List<Callable<String>> callables = new ArrayList<Callable<String>>();
ExecutorService executor = Executors.newCachedThreadPool();
callables.add(new Callable<String>() {
        public String call() {
            for (int i=0; i<100000; i++) {
                System.out.println("i "+i);
            }
            return "Task 1";
        }
    }
);
        
callables.add(new Callable<String>() {
        public String call() {
            for (int j=0; j<100000; j++) {
                System.out.println("j "+j);
            }
            return "Task 2";
        }
    }
);
        
callables.add(new Callable<String>() {
     public String call() {
          for (int k=0; k<100000; k++) {
              System.out.println("k "+k);
          } 
          return "Task 3";
      }
  }
);
try {
    List<Future<String>> futureLst = executor.invokeAll(callables);
    for (Future future : futureLst) {
        try {
            System.out.println(future.get());
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
executor.shutdown();
System.out.println("Time Taken - "+ (System.currentTimeMillis() - startTime));

The above code works fine as expected and prints the count and returns the string. The time taken for the above program to execute is "3229" milliseconds.

I rewrote the above program as below,

long startTime = System.currentTimeMillis();
for (int i=0; i<100000; i++) {
    System.out.println("i "+i);
}
for (int j=0; j<100000; j++) {
    System.out.println("j "+j);
}
for (int k=0; k<100000; k++) {
    System.out.println("k "+k);
}
System.out.println("Time Taken - "+ (System.currentTimeMillis() - startTime));

The time taken for this program is "3104" milliseconds which is lesser than the one coded with executing parallel.

So am I doing anything wrong in first program ? Is my first program running tasks in parallel, since I see without thread is taking less time?

Upvotes: 1

Views: 204

Answers (3)

Tagir Valeev
Tagir Valeev

Reputation: 100139

What your tasks mostly do is writing into standard output using the System.out.println call which is PrintStream.println method. It eventually calls PrintStream.write method which body is synchronized. Thus you just waste time on creating threads and synchronization overheads. As PrintStream is sequential by nature, it cannot output in parallel, so when single stream is writing, others just waiting for it. Some operations can be parallelized like your for loop and concatenation of string and number, but they are much faster than the output to stdout.

To gain the additional performance from the concurrency you should avoid using the shared sequential resource. In your case it's standard output stream.

Upvotes: 1

Duy Anh Pham
Duy Anh Pham

Reputation: 76

Your code is correct. The result is due to the computation is too simple and run too fast. Most of the run time is decided by the speed of console output so the benefit of multi-threading can not make up for the overhead of setting up & shutting down the thread pool. Also, the try-catch setup also adds a small overhead (very small, but enough to tangle the result in this simple scenario). --> You could try to increase the loop size (hint: use a static variable MAX_LOOP for faster testing) and you will see the different.

Upvotes: 0

mzc
mzc

Reputation: 3355

First one is sequential, second one is parallel -- that's fine.

It looks like the running time consists mainly of slow console write operations inside System.out.printlncall (see Why is System.out.println so slow?).

You should observe different behavior (and parallel version speedup) if you write to a file instead.

Upvotes: 1

Related Questions