区分 Java 线程和 OS 线程?

Posted

技术标签:

【中文标题】区分 Java 线程和 OS 线程?【英文标题】:Distinguishing between Java threads and OS threads? 【发布时间】:2010-12-25 16:20:24 【问题描述】:

如何区分正在运行的 Java 线程和本机线程?

在Linux中每个子进程都会有一个父进程,他们说0是所有进程的父进程,那么所有分叉的Java线程都会有一个父线程吗?

我如何知道哪个 Java 线程与 OS 线程相关(如果 Java 线程派生出本机进程线程)。

Java 线程和 OS 线程有什么命名约定吗?

一个正在运行的 Java 线程可以被另一个 Java 代码挂起或终止吗?

【问题讨论】:

Stephen C,我正在学习 Linux 线程命名和 Java 线程命名如何相互关联。还有,如何在 Linux 中管理 JVM 线程管理。 【参考方案1】:

在 Linux 上,Java 线程是使用本地线程实现的,因此使用线程的 Java 程序与使用线程的本地程序没有什么不同。 “Java 线程”只是属于 JVM 进程的线程。

在现代 Linux 系统(使用 NPTL 的系统)上,属于一个进程的所有线程都具有相同的进程 ID 和父进程 ID,但线程 ID 不同。您可以通过运行 ps -eLf 查看这些 ID。 PID列是进程ID,PPID列是父进程ID,LWP列是线程(LightWeight Process)ID。 “主”线程的线程 ID 与进程 ID 相同,其他线程将具有不同的线程 ID 值。

较旧的 Linux 系统可能使用不完全符合 POSIX 的“linuxthreads”线程实现,而不是 NPTL。在 linuxthreads 系统上,线程具有不同的进程 ID。

您可以通过将系统的 C 库 (libc) 作为独立程序运行并查看其输出中的“可用扩展”来检查您的系统是否使用 NPTL 或 linuxthreads。它应该提到“Native POSIX Threads Library”或 linuxthreads。 C 库的路径因系统而异:它可能是/lib/libc.so.6/lib64/libc.so.6(在基于 RedHat 的 64 位系统上)或类似 /lib/x86_64-linux-gnu/libc.so.6(在现代基于 Debian 的系统上,例如 Ubuntu) .

在操作系统级别,tads 没有名称;它们只存在于 JVM 中。

pthread_kill() C 函数可用于向特定线程发送信号,您可以使用该信号尝试从 JVM 外部终止该特定线程,但我不知道 JVM 会如何响应它.它可能会杀死整个 JVM。

【讨论】:

感谢 Wyard,我可以命名正在运行的线程并查询正在运行的线程的详细信息吗?我是从调试的角度问的。 线程的“名称”是 Java 特定的;要查看此类信息,您必须使用调试器连接到 JVM。从 JVM 外部您只能看到它的数字 ID,这是从 POSIX 角度来看它的唯一标识符。 如何在Shell提示符下显示Java线程名?如果我将探查器或调试器附加到正在运行的 JVM,我是否能够获取正在运行的 Java 线程名称并提供给 Shell 脚本? “您可以使用它来尝试从 JVM 外部杀死该特定线程” - 您可以使用 pthread_kill 将信号仅发送到与信号发送者在相同上下文中运行的线程。来自man pthread_kill(3) "pthread_kill() 函数将信号 sig 发送到与调用者处于同一进程中的线程。【参考方案2】:

没有标准;这完全取决于您使用的 Java 实现。另外,不要混淆“本机线程”和“本机进程”。进程是一个孤立的实体,无法看到其他进程的地址空间。线程是在本机进程的地址空间中运行的东西,它可以查看同一进程的其他线程的内存。

您在 Linux 上看到的是另一回事:某些版本的 Linux 在进程表中为父进程的每个线程创建一个条目。这些“过程”不是真正的过程(在隔离意义上)。它们是可以使用ps 命令列出的线程。您可以使用父 PID (PPID) 找到创建它们的进程。

【讨论】:

【参考方案3】:

没有通用的解决方案如何将 Java 线程映射到 OS 线程(如果有的话)。每个 JVM 实现都可以用不同的方式来实现。

还有一个纯 Java 线程实现,称为green threads。如果不支持本机线程或系统根本不是多线程的,这将用作后备。您不会在您的操作系统上看到任何绿色线程。

一个正在运行的 Java 线程可以被另一个 Java 代码挂起或终止吗?

如果它们在同一个 JVM 上运行,是的,使用 stop()。但这不是一个好的解决方案,可能有效,也可能无效。 interrupt() 允许线程如此安全地自行关闭。

据我所知,没有办法杀死 JVM 之外的线程。如果操作系统真的支持杀死线程,我不希望 Java 应用程序在之后正确运行!

【讨论】:

【参考方案4】:

一个可以运行的Java线程可以 从另一个 Java 中暂停或杀死 代码?

理论上是的。在实践中,Thread.kill()Thread.suspend() 方法已被弃用,因为它们不安全,除非在非常有限的情况下。基本问题是杀死或挂起一个 Java 线程可能会弄乱依赖它的其他线程,以及它可能正在更新的共享数据结构。

如果“另一个 Java 代码”意味着另一个 JVM,那么它工作的机会就更少了。即使你弄清楚了如何发送相关的线程信号,结果也是完全不可预测的。我敢打赌,“目标”JVM 会崩溃。

【讨论】:

你可以从你的 Java 代码中执行 Linux 命令来杀死在特定 JVM 下运行的特定线程。您甚至可以在 Windows 上执行此操作。但我想你可能是对的,这只会使该线程的父级 JVM 崩溃。如果你控制这两个程序,你可能应该开发某种 IPC 调用来告诉另一个进程中的线程无偿停止。

以上是关于区分 Java 线程和 OS 线程?的主要内容,如果未能解决你的问题,请参考以下文章

JAVA-初步认识-第十二章-Thread类中的方法线程名称

有啥方法可以区分主线程和它产生的任何线程吗?

如何区分进程和线程ps -eLf

从思维图到基础再到深入,java字符串查找不区分大小写

如何区分 C++ 中的高性能和低性能内核/线程?

HashTable HashMap区分