Continually process results of multi-thread worker Let's say we've got some SQL queries and want to display the results. Processing takes some time, so I do it multi-threaded.
The following works quite well for me. I reduced the code to the important parts and would be glad to get some comments on it:

Queries and results are stored in thread safe collections.

ConcurrentLinkedQueue&lt;String&gt; sqlQueries;
ConcurrentLinkedQueue&lt;ResultSet&gt; sqlResults;


In the GUI thread I start the worker threads which continuously get new queries from the sqlQueries, execute them, and put the results into sqlResults.

ExecutorService executorService = Executors.newFixedThreadPool(4);
for(int i=0; i&lt;4; i++){
    executorService.execute(new QueryThread(sqlResults, sqlQueries));
}
executorService.shutdown(); //threads terminate after they finish

//Result processing
while ((!executorService.isTerminated() || !sqlResults.isEmpty())) {
    Thread.Sleep(100); //sleep for some time
    while(!sqlResults.isEmpty()) {
        //process available results
    }
}


Within the threads I do sth like:

do{
    currentSqlQuery = sqlQueries.poll();
    if(currentSqlQuery != null) {
        sqlResults.add(executeQuery(currentSqlQuery));
    }
} while (currentSqlQuery != null)
I think you are misunderstanding the concept of Executor (and ExecutorService). It already acts as a queue, so you don't need to maintain a queue of your own. Your code actually creates one job per thread, and every job processes multiple questions from the queue. Instead, you should rather have one task per question:

Collection&lt;String&gt; questions = ...;
for (String question : questions) {
    executor.execute(new QueryTask(question));
}


Also note that you're calling your class QuestionThread. But it's not a thread, it's a task! Please always differ between task and thread: A task is a piece of work that should be done, while threads are a mechanism to execute tasks in parallel.

Your QueryTask should only execute one single query and return it as a result:

class QueryTask implements Callable&lt;String&gt; {
    private final String question;

    public QueryTask(String question) { this.question = question; }

    public String call() {
        // maybe long running
        // get and return answer!
    }
}


The processing part is flawed too, because you're doing a busy-wait there! Instead, you can solve your problem very elegant using a CompletionService. The full algorithm will then be as follows:

public void query(ExecutorService executor, Collection&lt;String&gt; questions, Consumer&lt;String&gt; answerConsumer) throws InterruptedException, ExecutionException {
    CompletionService ecs = new ExecutorCompletionService(executor);
    // execute all tasks
    for (String question : questions) {
        ecs.execute(new QueryTask(question));
    }

    // wait for tasks to complete and hand them over to consumer
    final int size = questions.size();
    for (int i = 0; i &lt; size; i++) {
        answerConsumer.accept(ecs.take().get());
    }
}


(The interface Consumer exists since Java 8; it can easily be replaced by something similar).

Appendix: Calling query from UI thread

Note that the calling thread is blocked until all questions and answers are processed. In case this is the UI thread, it will not be able to run UI events in the meantime. As a result, your UI will "freeze" (it will not react to any user input nor doing repaints of dirty UI regions). 

To solve this problem, the call to query must be asnychronous and the consumer must put the result into a UI updating task and hand it over to the UI thread (how this exactly works depends on the UI framework you are using. SWT: Display.(a)syncExec(...), Swing: SwingUtilites.invokeLater(...), JavaFX: Platform.runLater(...), ...). The following example will assume you're using JavaFX (it also uses Java 8 lambda expressions):

public void queryAsynchWithUIUpdate(Collection&lt;String&gt; questions) {
    Executor e = Executors.newSingleThreadExecutor();
    e.execute(() -&gt; {
        ExecutorService executor = Executors.newWorkStealingPool();
        query(executor, questions, answer -&gt; {
            Platform.runLater(() -&gt; {
                // update UI using answer, e.g.:
                answerTextField.setText(answer);
            });
        });
        executor.shutdown();
    });
    e.shutdown();
}