MultiThreadSearchProcessor { public Map<String, String> search(T module, List<String> bookList, String searchQuery) { Map<String, Future<Map<String, String>>> taskPool = new LinkedHashMap<>(); for (String bookID : bookList) { BookSearchProcessor<D, T> searchProcessor = new BookSearchProcessor<>(repository, module, bookID, searchQuery); SearchThread<D, T> thread = new SearchThread<>(searchProcessor); taskPool.put(bookID, executor.submit(thread)); } Map<String, String> searchRes = new LinkedHashMap<>(); for (Map.Entry<String, Future<Map<String, String>>> entry : taskPool.entrySet()) { try { searchRes.putAll(entry.getValue().get()); } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } } executor.shutdown(); return searchRes; } MultiThreadSearchProcessor(IModuleRepository<D, T> repository); Map<String, String> search(T module, List<String> bookList, String searchQuery);  }
@Test public void search() throws Exception { Map<String, String> results = searchProcessor.search(module, Arrays.asList("Gen", "Exo"), "бог"); assertThat(results.size(), equalTo(76)); }
@Test public void searchBookNotFound() throws Exception { Map<String, String> results = searchProcessor.search(module, Collections.singletonList("Sam"), "бог"); assertNotNull(results); assertThat(results.size(), equalTo(0)); }