简体   繁体   English

使用ExecutorService时的奇怪线程行为

[英]Strange thread behavior when using ExecutorService

Below is my code: 下面是我的代码:

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");
    }
}

The question is that the System.out.println(result); 问题是System.out.println(result); inside "watchThread" is never been called. 从未调用过“ watchThread”内部。 The console output looks like this: 控制台输出如下所示:

Executor Service thread
FX thread
Watch thread

But when I move the Future<String> future = executorService.submit(callable); 但是当我移动Future<String> future = executorService.submit(callable); to the inside of run method of "watchThread", the output change to: 到“ watchThread”的run方法内部,输出更改为:

FX thread
Watch thread
Executor Service thread
01234

which is I expected. 这是我的期望。 I also discovered that if the call() method has a longer task, say a Thread.sleep(1000) , the output change to the result I expected. 我还发现,如果call()方法的任务更长,例如Thread.sleep(1000) ,则输出更改为我期望的结果。

So why is that? 那为什么呢?

The thread you submit to executorService finishes before this line: 您提交给executorService的线程在此行之前完成:
while (!Thread.currentThread().isInterrupted() && !future.isDone()) { is called so future.isDone returns true and the while loop is not executed. while (!Thread.currentThread().isInterrupted() && !future.isDone()) {被调用,因此future.isDone返回truewhile循环不执行。

If you add Thread.sleep(1000) then it still runs and future.isDone returns false and the while loop executes. 如果添加Thread.sleep(1000)它仍将运行,并且future.isDone返回false,并执行while循环。 The same thing happens when you move Future<String> future = executorService.submit(callable); 当您移动Future<String> future = executorService.submit(callable);时,会发生相同的事情Future<String> future = executorService.submit(callable); inside watchThread . watchThread内部。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM