The problem is as follows: "Find prime numbers in the given interval". The algorithm is not that important. I came up with:
public class Prime {
 
 public static void main(String[] args) throws Exception {  
  final int threshold = 50_000_000;
  
  final long start = System.currentTimeMillis();
  
  final List candidates = IntStream.range(2, threshold).boxed().collect(Collectors.toList());
  final List primeNumbers = candidates.stream().filter(Prime::isPrime).collect(Collectors.toList());
  System.out.println("Execution time: " + System.currentTimeMillis() - start);
  
  System.out.println("Size: " + primeNumbers.size());
 }
 
 private static boolean isPrime(final int candidate) {
  for (int i = 2; i * i <= candidate; ++i) {
   if (candidate % i == 0) {
    return false;
   }
  }
  return true;
 }
}
  
Printed result:
Execution time: 55166 Size: 3001134The code is quite clean. However, it is executed sequentially and I have 4-cores (4.5 GHz each) - Core i5 Sandy Bridge - under the hood. Can we improve something? Of course we can! There is a new stream() API in Java 8 that allows for parallel processing. Just a small change to the code and we are set:
final ListThe output was:primeNumbers = candidates.parallelStream().filter(Prime::isPrime).collect(Collectors.toList()); 
Execution time: 16950 Size: 3001134Not so bad. parallelStream() uses default ForkJoin pool. Let's check the state of the threads:
4 threads are engaged in the computations: main thread and 3 workers. Can we obtain the result faster? How about using custom ForkJoin pool with 5 threads:
final ForkJoinPool forkJoinPool = new ForkJoinPool(5); final ListprimeNumbers = forkJoinPool.submit(() -> candidates.parallelStream().filter(Prime::isPrime). 
The output:collect(Collectors.toList())).get(); 
Execution time: 15504 Size: 3001134The state of the threads:


Excellent example. Thanks :)
ReplyDelete