线程的3种实现方式并深入源码简单分析实现原理(1)

简介: 线程的3种实现方式并深入源码简单分析实现原理(1)

前言


本文介绍下线程的3种实现方式并深入源码简单的阐述下原理


三种实现方式


Thread


image.png


image.png


image.png



深入源码简单刨析


Thread


Thread类实现了Runnable接口


枚举类 State


JVM中的线程必须只能是以上6种状态的一种。这些状态是JVM状态并不能和操作系统线程状态互相映射


  • NEW


线程刚创建,还未执行(start方法)


  • RUNNABLE


已就绪可运行的状态。
处于此状态的线程是正在JVM中运行的,
但可能在等待操作系统级别的资源,例如CPU时间片



  • BLOCKED


阻塞等待监视器锁
处于此状态的线程正在阻塞等待监视器锁,
以进入一个同步块/方法,
或者在执行完wait()方法后重入同步块/方法


  • WAITING


等待
执行完Object.wait无超时参数操作,
或者 Thread.join无超时参数操作(进入等待指定的线程执行结束),
或者 LockSupport.park操作后,线程进入等待状态。
一般在等待状态的线程在等待其它线程执行特殊操作,
例如:等待另其它线程操作Object.notify()唤醒或者Object.notifyAll()唤醒所有。


  • TIMED_WAITING



限时等待
Thread.sleep、Object.wait带超时时间、
Thread.join带超时时间、
LockSupport.parkNanos、
LockSupport.parkUntil这些操作会时线程进入限时等待


  • TERMINATED


终止,线程执行完毕


线程状态流转


JVM 线程状态流转图


image.png


注意:不要混淆操作系统线程状态和java线程状态。JVM中的线程必须只能是以上6种状态的一种!RUNNABLE = 正在JVM中运行的(Running)+ 可能在等待操作系统级别的资源(Ready)例如CPU时间片


  • 线程创建之后,不会立即进入就绪状态,因为线程的运行需要一些条件(比如内存资源),


  • 只有线程运行需要的所有条件满足了,才进入就绪状态。


  • 当线程进入就绪状态后,不代表立刻就能获取CPU执行时间,也许此时CPU正在执行其他的事情,因此它要等待。


  • 当得到CPU执行时间之后,线程便真正进入运行状态。


  • 线程在运行状态过程中,可能有多个原因导致当前线程不继续运行下去,比如用户主动让线程睡眠(睡眠一定的时间之后再重新执行)、用户主动让线程等待,或者被同步块给阻塞,此时就对应着多个状态:time waiting(睡眠或等待一定的事件)、waiting(等待被唤醒)、blocked(阻塞)。


  • 当由于突然中断或者子任务执行完毕,线程就会被消亡。
相关文章
|
2月前
|
Linux
一个进程最多可以创建多少个线程基本分析
一个进程最多可以创建多少个线程基本分析
230 1
|
4月前
|
监控 Linux 编译器
多线程死锁检测的分析与实现(linux c)-有向图的应用
在日常的软件开发中,多线程是不可避免的,使用多线程中的一大问题就是线程对锁的不合理使用造成的死锁,死锁一旦发生,将导致多线程程序响应时间长,吞吐量下降甚至宕机崩溃,那么如何检测出一个多线程程序中是否存在死锁呢?在提出解决方案之前,先对死锁产生的原因以及产生的现象做一个分析。最后在用有向环来检测多线程中是否存在死锁的问题。
57 0
|
10天前
|
SQL Dubbo Java
案例分析|线程池相关故障梳理&总结
本文作者梳理和分享了线程池类的故障,分别从故障视角和技术视角两个角度来分析总结,故障视角可以看到现象和教训,而技术视角可以透过现象看到本质更进一步可以看看如何避免。
83742 0
|
11天前
|
Java 调度
Java面试必考题之线程的生命周期,结合源码,透彻讲解!
Java面试必考题之线程的生命周期,结合源码,透彻讲解!
38 1
|
12天前
|
安全
并发编程之变量的线程安全分析的详细解析
并发编程之变量的线程安全分析的详细解析
11 0
|
2月前
|
存储 安全 Java
Java线程池ThreadPoolExcutor源码解读详解08-阻塞队列之LinkedBlockingDeque
**摘要:** 本文分析了Java中的LinkedBlockingDeque,它是一个基于链表实现的双端阻塞队列,具有并发安全性。LinkedBlockingDeque可以作为有界队列使用,容量由构造函数指定,默认为Integer.MAX_VALUE。队列操作包括在头部和尾部的插入与删除,这些操作由锁和Condition来保证线程安全。例如,`linkFirst()`和`linkLast()`用于在队首和队尾插入元素,而`unlinkFirst()`和`unlinkLast()`则用于删除首尾元素。队列的插入和删除方法根据队列是否满或空,可能会阻塞或唤醒等待的线程,这些操作通过`notFul
257 5
|
2月前
|
存储 安全 Java
Java线程池ThreadPoolExcutor源码解读详解07-阻塞队列之LinkedTransferQueue
`LinkedTransferQueue`是一个基于链表结构的无界并发队列,实现了`TransferQueue`接口,它使用预占模式来协调生产者和消费者的交互。队列中的元素分为数据节点(isData为true)和请求节点(isData为false)。在不同情况下,队列提供四种操作模式:NOW(立即返回,不阻塞),ASYNC(异步,不阻塞,但后续线程可能阻塞),SYNC(同步,阻塞直到匹配),TIMED(超时等待,可能返回)。 `xfer`方法是队列的核心,它处理元素的转移过程。方法内部通过循环和CAS(Compare And Swap)操作来确保线程安全,同时避免锁的使用以提高性能。当找到匹
247 5
|
2月前
|
存储 安全 Java
Java线程池ThreadPoolExcutor源码解读详解04-阻塞队列之PriorityBlockingQueue原理及扩容机制详解
1. **继承实现图关系**: - `PriorityBlockingQueue`实现了`BlockingQueue`接口,提供了线程安全的队列操作。 - 内部基于优先级堆(小顶堆或大顶堆)的数据结构实现,可以保证元素按照优先级顺序出队。 2. **底层数据存储结构**: - 默认容量是11,存储数据的数组会在需要时动态扩容。 - 数组长度总是2的幂,以满足堆的性质。 3. **构造器**: - 无参构造器创建一个默认容量的队列,元素需要实现`Comparable`接口。 - 指定容量构造器允许设置初始容量,但不指定排序规则。 - 可指定容量和比较
231 2
|
2月前
|
存储 安全 Java
Java线程池ThreadPoolExcutor源码解读详解03-阻塞队列之LinkedBlockingQueue
LinkedBlockingQueue 和 ArrayBlockingQueue 是 Java 中的两种阻塞队列实现,它们的主要区别在于: 1. **数据结构**:ArrayBlockingQueue 采用固定大小的数组实现,而 LinkedBlockingQueue 则使用链表实现。 2. **容量**:ArrayBlockingQueue 在创建时必须指定容量,而 LinkedBlockingQueue 可以在创建时不指定容量,默认容量为 Integer.MAX_VALUE。 总结起来,如果需要高效并发且内存不是主要考虑因素,LinkedBlockingQueue 通常是更好的选择;
180 1
|
2月前
|
存储 算法 Linux
【Linux 系统标准 进程资源】Linux 创建一个最基本的进程所需的资源分析,以及线程资源与之的差异
【Linux 系统标准 进程资源】Linux 创建一个最基本的进程所需的资源分析,以及线程资源与之的差异
136 0