JAVA和Nginx 教程大全

网站首页 > 精选教程 正文

Java线程实现_java线程实现原理

wys521 2025-02-20 18:25:24 精选教程 26 ℃ 0 评论

摘要

由于Java的并发和线程息息相关,我们今天看一下线程的实现方式轻量级,通用的线程实现方式有:

  • 使用内核线程实现
  • 使用用户线程实现
  • 使用用户线程和轻量级进程实现
  • Java线程实现

1. 内核线程

内核线程(KLT)其实就是直接由操作系统内核支持的线程,这种线程由内核完成切换。内核通过调度器对线程进行调度,将线程映射到处理器上。

在我们程序的实际使用中,不会直接去使用内核线程,而是使用内核线程的一种高级接口——轻量级进程(LWP),轻量级进程就属于我们常说的线程。轻量级进程和内核线程是1:1的关系。

由于内核线程的支持,每一个轻量级进程都是一个可以独立的调用单元,由于轻量级进程基于内核线程实现,内核线程直接由操作系统控制,所以我们可以不用线程的创建、切换、调度、阻塞,几乎所有的线程操作都可以交由操作系统内处理。

轻量级线程的缺点就是,我们的操作系统如果要使用轻量级进程必须要进行系统调用,系统调用需要在用户态和内核态进行切换,调用代价相对较高。其次每个轻量级进程对应一个内核线程,因此会占用一定的内核资源,因此一个操作系统支持轻量级进程的数量是有限的。

2. 用户线程

用户线程指的是完全建立在用户空间的线程库上,系统内核不能感知线程的存在。用户线程的所有操作都在用户态中完成,不需要内核的帮助。

用户线程的优点是不需要进行系统调用,调用代价低,缺点就是用户需要自己维护线程的创建、调度、同步、阻塞等操作,实现代价相对较高。

3. 用户线程+轻量级进程

用户线程+轻量级进程就是采用了上述两种实现的结合,通过这种结合我们可以取其精华去其糟粕。

首先用户线程是完全建立用户空间,用户线程的创建、切换调用代价较低,并且可以支持大规模的并发。

轻量级进程是用户线程和内核线程的之间的桥梁,通过轻量级进程,我们可以使用内核提供的线程调度功能和处理器映射(实现代价相对较高的操作)。在这种混合模式中,用户线程和轻量级进程的比例关系为N:M

4. Java线程实现

Java线程的实现方式就是采用用户线程+轻量级进程混合的模式,Java线程和轻量级进程的比例关系为1:1,至于为什么是1:1,我们可以分析一下:

我们在使用Java的Thread时,会调用start方法开启一个线程。

????public?synchronized?void?start()?{
????????/**
?????????*?This?method?is?not?invoked?for?the?main?method?thread?or?"system"
?????????*?group?threads?created/set?up?by?the?VM.?Any?new?functionality?added
?????????*?to?this?method?in?the?future?may?have?to?also?be?added?to?the?VM.
?????????*
?????????*?A?zero?status?value?corresponds?to?state?"NEW".
?????????*/
????????if?(threadStatus?!=?0)
????????????throw?new?IllegalThreadStateException();

????????/*?Notify?the?group?that?this?thread?is?about?to?be?started
?????????*?so?that?it?can?be?added?to?the?group's?list?of?threads
?????????*?and?the?group's?unstarted?count?can?be?decremented.?*/
????????group.add(this);

????????boolean?started?=?false;
????????try?{
????????????start0();
????????????started?=?true;
????????}?finally?{
????????????try?{
????????????????if?(!started)?{
????????????????????group.threadStartFailed(this);
????????????????}
????????????}?catch?(Throwable?ignore)?{
????????????????/*?do?nothing.?If?start0?threw?a?Throwable?then
??????????????????it?will?be?passed?up?the?call?stack?*/
????????????}
????????}
????}

????private?native?void?start0();

在start方法中有个关键的方法就是start0(),然后该方法是个native方法,这时候我们就需要看一下JDK的源码实现了,关于这个start0方法是在源码文件./jdk/src/share/native/java/lang.Thread.c中,如下图:

我们可以看到,start0方法实际上执行的JVM_StartThread方法,该方法所在的文件是./hotspot/src/share/vm/prims/jvm.cpp。

上图中JVM_StartThread方法中我们会new一个JavaThread,然后我们看一下这个JavaThread的实现, JavaThread的类定义在./hotspot/src/share/vm/runtime/thread.cpp中,如下图:

os::create_thread(this, thr_type, stack_sz);这里就是各个操作系统去创建线程了,这里我们假设我们的操作系统是linux操作系统,create_thread的方法存储在,./hotspot/src/os/linux/vm/os_linux.cpp中,linux中的线程创建方式是pthread,在create_thread方法中最终会有如下代码,完成轻量级进程的创建,如下:

通过上述分析,我们可以看到,在Java中每创建一个线程,我们变会创建一个轻量级进程,所以Java中的用户线程和轻量级进程为1:1。

本期的Java线程实现介绍到这,我是shysh95,我们下期再见!!!

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表