网站首页 > 精选教程 正文
Java线程的状态
1:初始线程,也就是new Thread,但是还没有调用start方法,还在JVM堆中,没有和OS真正的线程挂钩。
2:运行(RUNNABLE):调用了start,这时候os才会真正创建线程并和我们JVM堆中的线程挂钩,os创建完线程后,需要等待cpu调度,cpu还没轮到在os层面是就绪状态(ready),cpu轮到了就是运行中(running)这两种状态,在java层面统称为运行状态。
3:阻塞(BLOCKED):调用synchronized关键字。
4:等待(WAITING):比如调用了wait,join,park等等需要被唤醒。
5:超时等待(TIMED_WAITING):该状态不同于WAITING,它可以自己执行时间比如sleep(long),wait(long).... .... 。
6:中止:线程执行完成。
线程从创建到销毁都有哪些步骤
在操作系统层面,一个线程从创建到销毁大致经历以下步骤:
- 创建:当一个线程被创建时,操作系统会为它分配必要的资源,例如内存、寄存器等。此时,线程处于新建状态。
- 调度:操作系统的调度器会根据调度算法选择一个就绪状态的线程来运行。当一个线程被调度器选中后,它会获得CPU时间片,进入运行状态。
- 上下文切换:当一个正在运行的线程因为某些原因(例如时间片用完、等待I/O操作等)无法继续运行时,操作系统会将它切换出CPU,让其他线程来运行。在进行上下文切换时,操作系统会保存当前线程的上下文(例如寄存器值、程序计数器值等),以便在下一次调度这个线程时能够恢复它的运行状态。
- 挂起:有时候,一个线程可能需要等待某些事件(例如I/O操作完成、信号量可用等)才能继续运行。此时,操作系统会将这个线程挂起,让它进入阻塞状态。当等待的事件发生后,线程会重新进入就绪状态,等待被调度器选中运行。
- 销毁:当一个线程完成了它的任务或者被强制终止时,操作系统会回收它所占用的资源,并将其销毁。此时,线程的生命周期结束。
什么是线程的调度
线程调度是操作系统为线程分配CPU使用权的过程,决定了哪个线程会在何时运行。Java的线程调度是基于抢占式的,这意味着优先级更高的线程更可能被操作系统选中执行,但是它并不能保证一定会被执行。
线程调度主要有两种方式:
- 协同式线程调度(Cooperative Threads-Scheduling):在这种调度方式中,线程的执行时间由线程本身控制。线程会在完成其任务后,主动通知操作系统将控制权切换到另一个线程。协同式线程调度的主要优点是它的实现简单,因为线程在完成自己的任务后才通知系统进行线程切换,所以不存在线程同步的问题。然而,缺点也非常明显,如果一个线程出现问题,整个程序可能会阻塞。
- 抢占式线程调度(Preemptive Threads-Scheduling):在这种调度方式中,线程的执行时间以及是否需要切换由操作系统决定。这种情况下,线程的执行时间是不可控制的,这避免了“一个线程导致整个进程阻塞”的问题。Java线程调度就是基于抢占式的。有可能线程执行一会系统调度,然后就让另外一个线程执行了。
在Java中,虽然可以通过Thread.yield()方法让线程主动放弃当前分配的CPU时间,但线程无法控制自己何时获得CPU时间。
线程实现模型:内核线程,用户线程与混合实现
在我们的日常编程中,线程作为执行单位,常常被用来完成多任务的并行处理。然而,线程的底层实现模型却有多种,包括内核线程,用户线程,以及这两者的混合实现。它们各自的优缺点以及使用场景有所不同。
内核线程
内核线程(Kernel-Level Thread,KLT)是直接由操作系统内核支持和管理的线程。线程切换、调度以及任务的处理器映射,都由内核负责。每个内核线程都是一个独立的调度单元,所以即使某个线程在执行系统调用时被阻塞,也不会影响整个进程的执行。这种方式的优点是操作系统能够全面地掌控线程的生命周期,不会出现由于一个线程的问题影响整个进程的情况。然而,因为线程的创建、销毁和同步等操作都需要进行系统调用,而系统调用涉及到用户态和内核态的切换,所以这种方式的代价相对较高。
用户线程
用户线程,也就是在用户空间实现的线程,系统内核并不能感知到用户线程的存在以及其实现方式。用户线程的创建、销毁、切换和调度都在用户态完成,不需要内核的干预。因此,这种方式的操作可以非常快速且低消耗,并且能够支持大规模的线程数量。然而,用户线程的缺点在于,因为缺乏系统内核的支持,所有的线程操作都需要由用户程序自己去处理。例如,处理阻塞的问题、和实现上下文切换和抢占式调度,都会变得异常困难,甚至有些是无法实现的。
混合实现
混合实现模型将内核线程和用户线程结合起来使用,称为N:M实现。在这种模型中,既有用户线程也有内核线程。用户线程仍然在用户空间中创建,其创建、切换、销毁等操作仍然是廉价的,并且可以支持大规模的并发。同时,内核线程提供了线程调度和处理器映射的功能。在这种模式下,用户线程和内核线程的数量比是不定的,即N:M关系。
Java 线程的实现
Java线程的实现和系统内核线程是1:1关系,java线程的创建资源分配,以及上下文切换cpu调度都是由内核来完成的。java是不去干预的,这样实现的好处是简单。坏处就是浪费,举个例子,一个请求过来,可能也就几毫秒,但是java中就需要为一个单独的线程去处理浪费资源,除非是我们自己创建线程,自己调度,以及自己切换上下文。
为什么没有Running状态。
java线程和内核线程是1:1,是抢占式调度的。java线程调用start,进入RUNNABLE状态。os帮我们创建内核线程,进入就绪状态,等待cpu的调度。因为java线程是抢占式调度,完全不需要自己参与,什么时候从ready到running,又什么时候从running到ready,java是不知道的。
- 上一篇: 可动态调节参数的线程池实现
- 下一篇: Java线程在各个状态下调用start方法会发生什么事情?
猜你喜欢
- 2024-11-18 Java并发编程线程状态转换
- 2024-11-18 Java面试必考问题:线程的生命周期
- 2024-11-18 Java 19 虚拟线程的状态变化,停驻与锁定
- 2024-11-18 Java线程生命周期详解?
- 2024-11-18 线程从创建最终消亡,要经历的若干状态,你了解其中的多少?
- 2024-11-18 java线程状态之WAITING(等待)
- 2024-11-18 浅谈Java线程:线程基础知识扫盲
- 2024-11-18 Java线程在各个状态下调用start方法会发生什么事情?
- 2024-11-18 阻塞模型将会使线程休眠,为什么 Java 线程状态却是 RUNNABLE?
- 2024-11-18 可动态调节参数的线程池实现
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- nginx反向代理 (57)
- nginx日志 (56)
- nginx限制ip访问 (62)
- mac安装nginx (55)
- java和mysql (59)
- java中final (62)
- win10安装java (72)
- java启动参数 (64)
- java链表反转 (64)
- 字符串反转java (72)
- java逻辑运算符 (59)
- java 请求url (65)
- java信号量 (57)
- java定义枚举 (59)
- java字符串压缩 (56)
- java中的反射 (59)
- java 三维数组 (55)
- java插入排序 (68)
- java线程的状态 (62)
- java异步调用 (55)
- java中的异常处理 (62)
- java锁机制 (54)
- java静态内部类 (55)
- java怎么添加图片 (60)
- java 权限框架 (55)
本文暂时没有评论,来添加一个吧(●'◡'●)