Your task is perfectly parallel, and there is no need to use any synchronization. Right at all.
We divide this range (0 ... 1000000) into N ranges, and each range is calculated in a separate stream. And N is the number of threads.
public static int parallelSearch(int threadCount) throws Exception { ExecutorService threadPool = Executors.newFixedThreadPool(threadCount); Collection<Future<Integer>> futures = new ArrayList<>(threadCount); int limit = 1_000_000; int step = limit / threadCount; int x = 0; while (x < limit) { int finalX = x; futures.add(threadPool.submit(() -> search(finalX, finalX + step))); x += step; } int result = 0; for (Future<Integer> future : futures) result += future.get(); return result; } private static int search(int x, int limit) { int count = 0; while (x <= limit) { x++; if ((x % 10) + (x / 10) % 10 + (x / 100) % 10 == (x / 1000) % 10 + (x / 10000) % 10 + (x / 100000) % 10) { System.out.println(x); count++; } } return count; }