void () { if (!Registry.is("batch.inspections.process.project.usages.in.parallel")) { return; } final int setting = Registry.get("batch.inspections.number.of.threads").asInteger(); final int threadsCount = (setting > 0) ? setting : Runtime.getRuntime().availableProcessors() - 1; if (threadsCount == 0) { // need more than 1 core for parallel processing return; } LOG.info("Processing project usages using " + threadsCount + " threads"); // unbounded queue because tasks are submitted under read action, so we mustn't block myTasks = new LinkedBlockingQueue<>(); myFutures = new ArrayList<>(); final Application application = ApplicationManager.getApplication(); final ProgressManager progressManager = ProgressManager.getInstance(); final ProgressIndicator progressIndicator = progressManager.getProgressIndicator(); for (int i = 0; i < threadsCount; i++) { final Future<?> future = application.executeOnPooledThread(() -> { while (myFutures != null || !myTasks.isEmpty()) { try { final Runnable task = myTasks.poll(50, TimeUnit.MILLISECONDS); ProgressManager.checkCanceled(); if (task != null) { runTask(progressIndicator, task); } } catch (InterruptedException ignore) {} } }); myFutures.add(future); } }