我是做 java 的,语言不同,不过思想差不多。Task.Factory.StartNew(asycn ...),这是提交了个异步的任务,那它里面的执行时机就不确定了。你的猜测没错,这外面循环就 2 次,所以超大的概率,是循环结束后 Task 才开始执行。如果你的循环是 100 次的话,那么就有可能外面循环到 50 次的时候,第 30 次提交的 Task 开始执行。
断点调试的时候,之所以你没看出来问题,是因为你打了断点把异步任务给强行变回了同步任务。你打了两个断点,for 循环那里给主任务打了断点,看变量值那一行给 Task 打了断点,这样 Task 的执行时机,被人为控制的跟主任务同步了。
你的期望是,Task 里面的 dsIndex ,应该是 Task 提交时候的 dsIndex ,这样它就不能用主任务的 dsIndex 变量,因为后者是会被主任务更改值的。解决方法很简单,Task 里面不要直接使用 dsIndex 变量。final int dsIndexFinal = dsIndex ,Task 里面使用 dsIndexFinal 代替 dsIndex 即可。
@
Goooooos java final 并不能避免这种 bug 。你可以试试这段代码:
final AtomicInteger a = new AtomicInteger(1);
executorService.submit(()->{
Thread.sleep(5000);
System.out.println(a.get());
});
System.out.println(a.addAndGet(10));
像楼主这样的问题确实能避免,不过那是因为像 int dsIndex 这样的基本类型变量,压根就不能直接传递给匿名内部类,然后 IDE 会提醒你把它赋值给一个新的 final Integer 或 final AtomicInteger 变量后再传给匿名内部类去使用。