首页 > 编程知识 正文

阿里java笔试题,阿里面试题和答案java

时间:2023-05-05 03:31:16 阅读:48815 作者:2690

这个问题是安吉拉以前面试时问的问题,正好按照上一篇文章介绍了结束线程调用时的用户状态和内核状态的切换,然后一起说了同时并行的Java。

面试官:听前面面试官的话,说你的Java合并这个戴上很好,让我们深入交流一下;

我看了一眼:面试官头部稀疏的结缔组织,觉得这个面试并不容易,好在事先看了安吉拉的博客,准备好了,我回答说:“咳嗽,能掌握。”

面试官:你用过Java线程吧?

我:用过。

面试官:那么,你能谈谈Java线程和操作系统吗?

我:啊!

剧本不应该这样做啊。 开场首先是同步的,或者是volatile,然后是线程池和AQS,怎么上来,这是不应该调整的。

我:好的,那我分三段说。

用户状态线程内核状态线程Java线程源1 .用户状态线程第一阶段:

实际上,在早期,操作系统没有线程概念,线程是后来添加的,操作系统最初只有进程,操作系统分配资源的最小单位是进程,在进程和进程之间存在关联隔离

第二阶段:

在早期多线程中,线程是在用户空间中实现的。

什么意思? 据了解,内存分为用户空间和系统空间。 系统空间用于操作系统,用户空间用于APP应用程序。 如果APP应用程序需要访问系统空间,则必须调用系统以从用户状态切换到内核状态。 在此,请详细参阅上一篇文章: [关于用户空间和内核空间]

那么如何在用户空间中实现多线程呢?

实际上,操作系统是按进程维调度的,操作系统不管理用户线程切换,而APP应用程序本身在用户空间中实现线程的创建、维护和调度。 型号如下图:

如果线程在用户空间中实现,则操作系统不知道线程的存在,操作系统只能看到进程,不能看到线程。 所有线程都在用户空间中实现。 从操作系统来看,每个进程只有一个线程。

这种方式的好处之一是,即使操作系统不支持线程,库函数也可以支持线程。 JDK1.1使用的是绿色线程,而不是原始线程。

以下是关于green thread的说明。 green thread不是今天的重点,所以我不详细说明。

green threads是由运行时或虚拟机(VM )调度的线程,而不是本地基础操作系统。 绿色线程与基本系统功能无关,模拟多线程的执行。 由于此线程的管理预配是在用户空间而不是内核空间中进行的,因此它可以在没有本机线程支持的环境中运行。

在Java 1.1中,绿色线程是JVM中唯一使用的线程模型,至少在Solaris中。 由于与本机线程相比,绿色线程在使用上存在一些限制,因此在以后的Java版本中放弃绿色线程,转而使用native threads

这种模型的优点和缺点显然是:

由于缺点:操作系统不知道线程的存在,因此CPU时间片切换以进程为维度,如果进程中的线程执行了一些耗时的操作,则会阻止整个进程。 此外,当某个进程的某个线程(绿色线程)进行系统调用时,例如,如果由于网络I/o或页面错误等操作而导致线程被阻止,则操作系统认为该进程的其他线程

优点使用:库函数实现的线程切换消除了从用户状态到内核状态的切换。 这个味道不为人知。 顺便说一下,Go协和式组织借鉴了这一思想的一部分。

2 .内核状态线程紧跟在Java1.2之后。 Linux上的JVM基于pthread实现,Java线程依赖操作系统实现,可以直接说是1:1的关系。

现在的Java中线程的本质,其实就是操作系统中的线程

此外,许多资料显示,Java线程实现采用轻量级进程(LWP ),实际上是从Linux内核2.6开始,用新的线程实现方式NPTL替换LinuxThread,NPTL除了LinuxThread之外

LinuxThread使用1 * 1机型。 也就是说,内核的管理实体对应于每个用户状态线程。 此内核的管理实体是一个进程,也称为轻量级进程(LWP )

如果您想了解更多有关NPTL的信息,请去看NPTL的详细信息。

我们知道每个线程都有自己的线程上下文。 线程上下文包含线程的ID、堆栈、程序计数器和通用寄存器等的集合。 总觉得上下文这个词很模糊,但我发现找不到更合适的词。

线程有自己的独立上下文,由操作系统调度,但也有线程消耗资源过大的缺点。 例如,在linux上,一个线程的默认堆栈大小为1M,单个创建数万个线程有点费劲。 所以后来,在编程语言的层面上,出现了一种叫协和式的东西。

协议模式类似于上述两种方式的组合,在用户状态下进行线程资源的切换,使操作系统在内核层进行线程调度。

协和式与操作系统线程存在映射关系。 例如,我们需要建设m个协议,在n个线程上执行。 这就是m: n的方案。

这n个线程也是靠操作系统调度实现。

另外协程是按需使用栈内存的,所以理论上可以轻轻松松创建百万级的协程。

目前协程这块支持的最好的是go语言, 不过现在OpenJDK社区也正在为JDK增加协程的支持。

3. 线程的源码

我们在Java中调用 new Thread(Runnable ***).start() 方法时,怎么从用户态切到内核态,发送系统调用,在操作系统内核层中创建一个线程的呢?

这个可以一步步往下钻,文章最后会贴源代码地址,这里只把头和尾贴出来,关键点在JVM层系统调用创建线程的源码。

首先是native方法: private native void start0();

下到Thread.c 文件,:

44行,方法映射;追着 JVM_StartThread 进到 jvm.cpp

linux 系统下的,看 src/hotspot/os/linux/os_linux.cpp

主要关注 pthread_create 这里,是通过linux 的 c库函数完成系统调用,从用户态切到内核态完成线程的创建。

文中源代码地址:

Thread.c

pthread_create

os_linux

最后说下怕误导大家,说下头发不属于结缔组织。

网友喜欢把剪头发说成:明天我就要去动手术了,头部结缔组织群体切割手术,祝我好运 !

参考:

[Understanding java’s native threads and the jvm]

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。