使用ExecutorService时出现奇怪的线程行为

时间:2017-08-06 14:41:42

标签: java multithreading javafx

以下是我的代码:

public class Controller {
    public Button button_submitWork;

    @FXML
    public void handleSubmitWork(ActionEvent event) {
        final ExecutorService executorService = Executors.newFixedThreadPool(1, r -> {
            Thread t = Executors.defaultThreadFactory().newThread(r);
            t.setDaemon(true);
            return t;
        });//set thread daemon, let all threads terminate when the program is closed.
        Callable<String> callable = new Callable<String>() {
            @Override
            public String call() throws Exception {
                System.out.println("Executor Service thread");
                StringBuilder stringBuilder_output = new StringBuilder();
                for (int k = 0; k < 5; k++) {
                    stringBuilder_output.append(k);
                }
                //Thread.sleep(1000);
                return stringBuilder_output.toString() + "\n";
            }
        };
        Future<String> future = executorService.submit(callable);//Weird line. 
        //This line must be placed inside the "watchThread" to get the result, but why???
        Thread watchThread = new Thread(new Runnable() {
            @Override
            public void run() {
                //<----------Moving to here solve the problem!
                System.out.println("Watch thread");
                while (!Thread.currentThread().isInterrupted() && !future.isDone()) {
                    try {
                        String result = future.get();
                        System.out.println(result);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } catch (ExecutionException e) {
                        e.printStackTrace();
                    } finally {
                        executorService.shutdownNow();
                    }
                }
            }
        });
        watchThread.setDaemon(true);
        watchThread.start();
        System.out.println("FX thread");
    }
}

问题是“watchThread”里面的System.out.println(result);从未被调用过。控制台输出如下所示:

Executor Service thread
FX thread
Watch thread

但是当我将Future<String> future = executorService.submit(callable);移动到“watchThread”的run方法内部时,输出更改为:

FX thread
Watch thread
Executor Service thread
01234

这是我的预期。 我还发现,如果call()方法的任务较长,比如Thread.sleep(1000),则输出会更改为我预期的结果。

那为什么呢?

1 个答案:

答案 0 :(得分:2)

您提交给executorService的主题在此行之前完成:
调用while (!Thread.currentThread().isInterrupted() && !future.isDone()) {以便future.isDone返回true并且不执行while循环。

如果添加Thread.sleep(1000),它仍会运行,future.isDone返回false并执行while循环。在Future<String> future = executorService.submit(callable);内移动watchThread时会发生同样的事情。