使用不同线程时,源代码运行的java顺序
当我第一次开始学习Java时,我了解到代码从顶部读取到底部。我想你们都明白,不需要编写代码来解释这个问题
但是当我使用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循环将首先运行,在控制台中打印"rest od code.."
之前至少打印一个"working"
。我错了。我的结果总是这样:
rest od code..
working
working
working
working
working
有人能告诉我,在'rest of code'
之前,控制台中是如何至少打印一个'working'
的吗?有没有可能代码运行得太快,以至于在到达('rest of code')之前没有机会实际运行任何run() method
[注]如有任何修改,将不胜感激
# 1 楼答案
线程正在并发执行(主线程和工作线程),尝试在println in main方法之前暂停主线程执行一段时间,结果会有所不同
重复运行,并且很可能在主线程暂停时执行工作线程
预期的是记忆一致性效应:
“在将可运行或可调用任务提交给ExecutorService之前,线程中的操作发生在该任务执行任何操作之前,而该操作又发生在通过Future.get()检索结果之前。”
# 2 楼答案
不同的线程独立运行。无法保证主线程和它创建的任何“可运行程序”之间的相对顺序
这与代码是否从上到下“读取”无关;对于执行来说,这不是一个有用的概念。下面是一个非自上而下执行的简单非线程示例:
回到当前的问题:您会注意到,‘execute’的documentation指的是在‘将来某个时候’运行Runnable
实际上,这可能类似于在队列中放入一个条目,然后唤醒一个线程。让线程启动并运行通常需要比直线代码路径更多的机器指令
所以,是的,你对“跑得这么快”的解释或多或少是正确的,只是“跑得这么快”并不是真的盲目地快