In order to implement multi threaded search we need to adjust the logic that creates the slices.
The new slice logic should take the following into account:

- A minimum doc count per slice. In order to avoid a number of aggregations to produce in-accurate results, a slice should at least contain 10% of the total documents in the Lucene index.
- A maximum number of slices. The number of slices that a shard level search creates should be capped. To avoid creating more slices than available search threads.
server/src/main/java/org/elasticsearch/search/internal/ContextIndexSearcher.java
private final Set<Runnable> runnables = new HashSet<>();
        private Runnable add(Runnable action) {
            Objects.requireNonNull(action, "cancellation runnable should not be null");
            if (runnables.add(action) == false) {
                throw new IllegalArgumentException("Cancellation runnable already added");
            }
            return action;
        }
        private void remove(Runnable action) {
            runnables.remove(action);
        }
        @Override
        public void checkCancelled() {
            for (Runnable timeout : runnables) {
                timeout.run();
            }
        }
        @Override
        public boolean isEnabled() {
            return runnables.isEmpty() == false;
        }
        public void clear() {
            runnables.clear();
        }
    }
    private static class QueueSizeBasedExecutor {