使用不同线程时我们的源代码顺序为 运行

Order in which our source code is run when using different threads

刚开始学习Java的时候,了解到code是从top读取的 底部 。不需要编写代码来解释这个解释,我想你们都明白了。

但是当我使用 multi-threading 时会发生什么?假设我有这个简单的例子:

public class Tester {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newSingleThreadExecutor();
        for (int i = 0; i < 5; i++) {
            executorService.execute(new WorkingClass());
        }
        System.out.println("rest od code..");
        executorService.shutdown();
    }
}

class WorkingClass implements Runnable{
    @Override
    public void run() {
        System.out.println("working");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

我正在使用 singleThreadExecutor,因此 1 个线程 应该完成那些 5 个任务。我原以为我的 for 循环 会先 运行,在 console[= 中打印 "rest od code.." 之前至少打印一个 "working" 39=]。我错了。我的结果总是这样:

rest od code..
working
working
working
working
working

谁能告诉我为什么 'rest of code' 之前 console 中至少打印了一个 'working'?代码 运行 是否有可能如此之快以至于它在到达 ('rest of code') 之前没有机会实际 运行 任何 run() method

[注意]任何编辑都将不胜感激,以帮助改进这个问题。

不同线程运行独立。无法保证您的主线程与其创建的任何 'Runnables' 之间的相对顺序。

这与代码是否'read'从上到下无关;这不是执行的有用概念。这是 non-top-to-bottom 执行的简单 non-thread 示例:

   void method1() {
       method2();
       System.out.println("one");
   }

   void method2() {
       System.out.println("two");
   }

回到手头的问题:您会注意到 'execute' 的 documentation 指的是 运行 在 'some time in the future' 处运行 Runnable。

实际上,这可能类似于将一个条目放入队列然后唤醒一个线程。启动线程并 运行ning 通常需要比 straight-line 代码路径更多的机器指令。

所以,是的,你的 'runs so fast' 解释是 more-or-less 的,除了 'so fast' 并不是真的快得让人眼花缭乱。

线程并发执行(主线程和工作线程),尝试在main方法中的println之前暂停主线程执行一小会儿,结果会有所不同。

Thread.sleep(1000);
System.out.println("rest od code..");
executorService.shutdown();

重复 运行 并且您的工作线程在主线程暂停时执行的可能性很大。

期待内存一致性效果:

“在将 Runnable 或 Callable 任务提交给 ExecutorService 之前线程中的操作 happen-before 该任务采取的任何操作,进而 happen-before 结果通过 Future.get()"