【高薪程序员必看】万字长文拆解Java并发编程!(2 2-1)

简介: 🔥【高薪程序员必看】万字长文拆解Java并发编程!面试官看了直呼内行,90%人不知道的线程安全骚操作!💻🚀《16个高频面试灵魂拷问+底层源码暴击》🔥👉戳这里看如何用1个月经验吊打3年程序员!📌 核心痛点暴击:1️⃣ 面了8家都被问synchronized锁升级?一张图看懂偏向锁→重量级锁全过程!2️⃣ 线程池参数不会配?高并发场景下这些参数调优救了项目组命!3️⃣ volatile双重检测单例模式到底安不安全?99%人踩过的内存可见性大坑!

目录

2. Java线程

2.1. 线程的创建方式

2.1.1. 直接使用Thread

2.1.2. Runnable配合Thread

2.1.3. FutureTask配合Thread

2.1.4. lambda表达式

2.2. 查看进程线程

2.2.1. window

2.2.2. Linux

2.2.3. java

2.3. 线程运行原理

2.3.1. 栈与栈帧

2.3.2. 线程上下文切换

2.4. 线程方法对比

2.4.1. start与run

2.4.2. sleep与yield


2. Java线程

Java线程的执行顺序是由底层的任务调度器去实现的,不由我们控制

2.1. 线程的创建方式

2.1.1. 直接使用Thread

Thread:将线程的创建和任务的创建合并在一起

//通过Thread创建任务
public static void main(String[] args) {
    Thread t1 = new Thread("t1"){
        @Override
        public void run() {
            log.info("t1");
        }
    };
    t1.start();
    log.info("main");
}

image.gif

2.1.2. Runnable配合Thread

Runnable:将任务的创建和线程的创建分开,脱离了Thread继承体系,更容易与线程池等高级API结合

//先创建Runnable任务再创建线程
public static void main(String[] args) {
    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            log.info("t1");
        }
    };
    Thread t1 = new Thread(runnable,"t1");
    t1.start();
    log.info("main");
}

image.gif

2.1.3. FutureTask配合Thread

public static void main(String[] args) throws ExecutionException, InterruptedException {
    FutureTask<String> task = new FutureTask<>(()->{
        log.debug("task");
        return "task";
    });
    Thread t1 = new Thread(task,"t1");
    t1.start();
    log.debug("main");
    log.debug("结果是{}",task.get());
}

image.gif

2.1.4. lambda表达式

JDK8后会将只有一个抽象方法的接口(例如Runnable)加上@FunctionalInterface表示当前接口可以使用lambda表达式

image.gif 编辑

//lambda表达式简化写法
public static void main(String[] args) {
    Thread t1 = new Thread(()-> log.info("t1"),"t1");
    t1.start();
    log.info("main");
}

image.gif

2.2. 查看进程线程

2.2.1. window

  • tasklist:查看进程列表
  • tasklist | findstr xxx:查看指定字符串的进程列表
  • task kill /F /PID:强制杀死指定PID的进程

2.2.2. Linux

  • ps -ef:查看进程列表
  • ps -ef | grep java:查看java进程命令
  • kill -f pid:杀死指定pid的进程
  • top:查看详细进程信息

2.2.3. java

  • jps:查看所有java进程
  • jstack pid:查看这个时刻指定pid的java进程所有线程状态
  • jconsole:图形化界面连接Java进程中的线程运行情况

2.3. 线程运行原理

2.3.1. 栈与栈帧

JavaVirtualMachineStacks(Java虚拟机栈),JVM中由堆、栈、方法区所组成,其中栈内存是给线程用的

  • 每个线程启动后,虚拟机就会为其分配一块栈内存。·
  • 每个栈由多个栈帧(Frame)组成,对应着每次方法调用时所占用的内存·
  • 每个线程只能有一个活动栈帧,对应着当前正在执行的那个方法

断点右键指定线程可以调试多个线程运行情况

image.gif 编辑

2.3.2. 线程上下文切换

线程会因为一些原因导致CPU不能继续执行当前线程,转而执行另外一个线程:

  • 当前线程的CPU时间片用完
  • 垃圾回收时,只有执行垃圾回收的线程能运行,其他的工作线程都会被阻塞
  • 有比当前线程更高优先级的线程需要运行
  • 当前线程内部调用了sleep,wait,lock,synchronized,yield,join,park等方法

当线程发生上下文切换(Context Switch)时,操作系统会保留当前线程的运行状态,同时恢复另外一个线程的状态,Java中的完成这个过程的是程序计数器,它会记录下一条字节码指令的地址,线程上下文切换时,由程序计数器提供地址给Java找到继续运行的线程

  • Java中的线程状态包括:程序计数器,栈帧信息,例如局部变量,操作数栈,返回地址等等
  • 频繁发生线程上下文切换会影响程序的性能

2.4. 线程方法对比

2.4.1. start与run

start:

  • 开启线程,并用开启的线程执行run方法.
  • 调用start方法会让线程状态从new状态进入runnable状态
  • start方法只能调用一次,因为线程处于runnable状态时不能再次开启线程

run:

  • 执行run方法,不开启新的线程,调用的只是普通方法.
  • 调用run方法不会对线程状态产生影响

2.4.2. sleep与yield

sleep:

  • 调用sleep方法会让线程状态从running状态进入timewaiting状态
  • 其他线程可以调用interrupt方法打断正在睡眠的线程,此时sleep方法会抛出InterruptedException
  • 睡眠结束的线程可能不会立即被调用
  • TimeUnit的sleep方法比Thread的sleep方法有更好的可读性

yield:

  • 调用yield方法会让线程状态从running状态进入runnable状态,然后调度其他同优先级的runnable状态线程,如果没有同优先级的线程,当前线程还是会运行,相当于是当前线程做出一次让步
  • 具体的实现依赖于操作系统的任务调度器
目录
相关文章
|
21天前
|
人工智能 Kubernetes Java
回归开源,两位 Java 和 Go 程序员分享的开源贡献指引
Higress是一个基于Istio和Envoy的云原生API网关,支持AI功能扩展。它通过Go/Rust/JS编写的Wasm插件提供可扩展架构,并包含Node和Java的console模块。Higress起源于阿里巴巴,解决了Tengine配置重载及gRPC/Dubbo负载均衡问题,现已成为阿里云API网关的基础。本文介绍Higress的基本架构、功能(如AI网关、API管理、Ingress流量网关等)、部署方式以及如何参与开源贡献。此外,还提供了有效的开源贡献指南和社区交流信息。
257 34
|
9天前
|
Java 数据库连接 API
2025 更新必看:Java 编程基础入门级超级完整版指南
本教程为2025更新版Java编程基础入门指南,涵盖开发环境搭建(SDKMAN!管理JDK、VS Code配置)、Java 17+新特性(文本块、Switch表达式增强、Record类)、面向对象编程(接口默认方法、抽象类与模板方法)、集合框架深度应用(Stream API高级操作、并发集合)、模式匹配与密封类等。还包括学生成绩管理系统实战项目,涉及Maven构建、Lombok简化代码、JDBC数据库操作及JavaFX界面开发。同时提供JUnit测试、日志框架使用技巧及进阶学习资源推荐,助你掌握Java核心技术并迈向高级开发。
72 5
|
15天前
|
JavaScript 前端开发 Java
Java 编程进阶实操中工具集整合组件封装方法与使用指南详解
本文详细介绍Hutool工具集和图书管理系统相关组件的封装方法及使用示例。通过通用工具类封装(如日期格式化、字符串处理、加密等)、数据库操作封装(结合Hutool DbUtil与MyBatis)、前端Vue组件封装(图书列表与借阅表单)以及后端服务层封装(业务逻辑实现与REST API设计),帮助开发者提升代码复用性与可维护性。同时,提供最佳实践建议,如单一职责原则、高内聚低耦合、参数配置化等,助力高效开发。适用于Java编程进阶学习与实际项目应用。
83 10
|
9天前
|
Oracle Java 关系型数据库
java 编程基础入门级超级完整版教程详解
这份文档是针对Java编程入门学习者的超级完整版教程,涵盖了从环境搭建到实际项目应用的全方位内容。首先介绍了Java的基本概念与开发环境配置方法,随后深入讲解了基础语法、控制流程、面向对象编程的核心思想,并配以具体代码示例。接着探讨了常用类库与API的应用,如字符串操作、集合框架及文件处理等。最后通过一个学生成绩管理系统的实例,帮助读者将理论知识应用于实践。此外,还提供了进阶学习建议,引导学员逐步掌握更复杂的Java技术。适合初学者系统性学习Java编程。资源地址:[点击访问](https://pan.quark.cn/s/14fcf913bae6)。
56 2
|
16天前
|
前端开发 Java 数据库连接
Java 编程进阶实操之工具集整合应用指南
本文聚焦Java编程进阶实操,涵盖并发编程、性能优化及数据库操作优化等核心知识点,并结合Hutool、Postman、Git等实用工具,提供从理论到实践的学习路径。通过小型图书管理系统实战项目,详细解析技术选型与实现步骤,助力开发者掌握Spring Boot、MyBatis等框架应用。同时展望Java新特性与技术趋势,为职业发展奠定基础。资源链接:[点此获取](https://pan.quark.cn/s/14fcf913bae6)。
49 1
|
25天前
|
Java 开发者
Java编程实用技巧:提升代码质量与开发效率
Java作为一门成熟且广泛应用的编程语言,掌握一些实用技巧可以显著提高开发效率和代码质量。以下是值得Java开发者掌握的实用技巧:
42 6
|
10天前
|
人工智能 Java API
Java并发编程之Future与FutureTask
本文深入解析了Future接口及其实现类FutureTask的原理与使用。Future接口定义了获取任务结果、取消任务及查询任务状态的规范,而FutureTask作为其核心实现类,结合了Runnable与Future的功能。文章通过分析FutureTask的成员变量、状态流转、关键方法(如run、set、get、cancel等)的源码,展示了异步任务的执行与结果处理机制。最后,通过示例代码演示了FutureTask的简单用法,帮助读者更直观地理解其工作原理。适合希望深入了解Java异步编程机制的开发者阅读。
|
27天前
|
网络协议 Java 大数据
【高薪程序员必看】万字长文拆解Java并发编程!(1)
📌 核心痛点暴击:1️⃣ 面了8家都被问synchronized锁升级?一张图看懂偏向锁→重量级锁全过程!2️⃣ 线程池参数不会配?高并发场景下这些参数调优救了项目组命!3️⃣ volatile双重检测单例模式到底安不安全?99%人踩过的内存可见性大坑!💡 独家亮点抢先看:✅ 图解JVM内存模型(JMM)三大特性,看完再也不怕指令重排序✅ 手撕ReentrantLock源码,AQS队列同步器实现原理大揭秘✅ 全网最细线程状态转换图(附6种状态转换触发条件表)
45 0
|
18天前
|
算法 Java 调度
Java多线程基础
本文主要讲解多线程相关知识,分为两部分。第一部分涵盖多线程概念(并发与并行、进程与线程)、Java程序运行原理(JVM启动多线程特性)、实现多线程的两种方式(继承Thread类与实现Runnable接口)及其区别。第二部分涉及线程同步(同步锁的应用场景与代码示例)及线程间通信(wait()与notify()方法的使用)。通过多个Demo代码实例,深入浅出地解析多线程的核心知识点,帮助读者掌握其实现与应用技巧。
|
4月前
|
存储 监控 Java
【Java并发】【线程池】带你从0-1入门线程池
欢迎来到我的技术博客!我是一名热爱编程的开发者,梦想是编写高端CRUD应用。2025年我正在沉淀中,博客更新速度加快,期待与你一起成长。 线程池是一种复用线程资源的机制,通过预先创建一定数量的线程并管理其生命周期,避免频繁创建/销毁线程带来的性能开销。它解决了线程创建成本高、资源耗尽风险、响应速度慢和任务执行缺乏管理等问题。
261 60
【Java并发】【线程池】带你从0-1入门线程池