以下代码创建 100 个新的 java 线程并运行它们。
class ThreadTest {
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
final int tNo = i;
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("thread #" + tNo);
}
}).start();
}
}
}
当我运行上面的代码并使用 strace 记录由此执行的系统调用时,我找不到任何正在创建新线程的系统调用(可能是 clone())。
但是当我使用 ps -eLf 命令检查上述进程的线程时,它会列出 (>100) 个具有不同线程 ID 的线程。
这些线程是如何在没有任何系统调用的情况下创建的?如果 jvm 在用户空间中创建线程,那么这些线程不应该被 ps -eLf 列出。
strace 命令的输出结果
mprotect(0xf95000, 8876032, PROT_READ|PROT_EXEC) = 0
munmap(0xf7762000, 92395) = 0
mmap2(NULL, 331776, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK, -1, 0) = 0xfffffffff770f000
mprotect(0xf770f000, 4096, PROT_NONE) = 0
clone(child_stack=0xf775f494, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0xf775fbd8, tls=0xf775fbd8, child_tidptr=0xffdb53d0) = 31692
futex(0xf775fbd8, FUTEX_WAIT, 31692, NULLthread #1
thread #5
thread #4
thread #3
.....
) = 0
exit_group(0) = ?
我删除了启动 jvm 所需的初始系统调用。显示的唯一克隆系统调用是用于创建主线程的调用。
最佳答案
在我运行 Oracle Java 8u5 的机器上,我看到与运行 strace java ThreadTest
非常相似的输出。但是,当我启用 -f
标志以跟随子进程时,我看到进行了数十次 clone()
调用。
您对 strace
的调用告诉它只关注直接启动的进程(JVM 引导线程),并且它只生成主线程。然后 that 线程就是调用 clone()
来创建所有 worker 的线程。
关于java - 当我在 Java 中创建多个线程时,为什么没有调用系统调用来创建线程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24485255/