空荡荡的身体永远运行

时间:2018-10-19 09:04:11

标签: java

我构建以下演示代码来测试java.util.concurrent.CompletableFuture.runAsync函数:

import java.util.ArrayList;
import java.util.List;

public class TestClass {

    public static void main(String[] args) throws Exception{
        // TODO Auto-generated method stub
        java.util.concurrent.CompletableFuture.runAsync(    () ->{startCall(1);});
        java.util.concurrent.CompletableFuture.runAsync(    () ->{startCall(2);});
        java.util.concurrent.CompletableFuture.runAsync(    () ->{startCall(3);});
        //Add sleep if case mainthread is to fast
        Thread.sleep(1000);
        while (!RunningTasks.isEmpty());
        System.out.println("Shutting down");
    }

    private static List<String> RunningTasks=new ArrayList<String>(); 

    private static void startCall(int cn) {

        RunningTasks.add("TASK"+cn);

        int sleeptime = (int) (Math.random()*10*1000);

        System.out.println("Sleeptimer: "+sleeptime+" for instance: "+cn);
        try {
            Thread.sleep(sleeptime);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println("Task "+cn+" finished");
        RunningTasks.remove("TASK"+cn);
        System.out.println("RunningTasks: "+RunningTasks.size() +" is empty? "+RunningTasks.isEmpty());
    }       
}

如果我在正常模式下的日食中运行此代码(因此只需按一下运行),一切都可以预期,则while循环似乎永远不会真正停止,这意味着“关闭”永远不会被打印。

如果我在DebugMode中运行代码并在 RunningTasks:0为空时立即在条件上设置断点? true 被打印,而while检测到条件为假并退出。

如果我放了一些代码,例如将一个sysout命令放到while循环中,它也会像预期的那样退出。

我错过了什么吗,或者确实是Java错误吗?

1 个答案:

答案 0 :(得分:2)

在运行代码时,可能会优化程序。因此,您的计算机可能会在while循环中缓存条件的结果。如果要防止这种缓存,可以编写:

private static volatile List<String> RunningTasks=new ArrayList<String>(); 

关键字 volatile告诉计算机不要缓存结果,这样您就可以在每次迭代中真正查询RunningTasks.isEmpty()的结果,而无需使用缓存的值。