【高薪程序员必看】万字长文拆解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状态线程,如果没有同优先级的线程,当前线程还是会运行,相当于是当前线程做出一次让步
  • 具体的实现依赖于操作系统的任务调度器
相关文章
|
5月前
|
Java
如何在Java中进行多线程编程
Java多线程编程常用方式包括:继承Thread类、实现Runnable接口、Callable接口(可返回结果)及使用线程池。推荐线程池以提升性能,避免频繁创建线程。结合同步与通信机制,可有效管理并发任务。
244 6
|
5月前
|
IDE Java 编译器
java编程最基础学习
Java入门需掌握:环境搭建、基础语法、面向对象、数组集合与异常处理。通过实践编写简单程序,逐步深入学习,打牢编程基础。
318 1
|
6月前
|
SQL Java 数据库
2025 年 Java 从零基础小白到编程高手的详细学习路线攻略
2025年Java学习路线涵盖基础语法、面向对象、数据库、JavaWeb、Spring全家桶、分布式、云原生与高并发技术,结合实战项目与源码分析,助力零基础学员系统掌握Java开发技能,从入门到精通,全面提升竞争力,顺利进阶编程高手。
1100 3
|
5月前
|
安全 前端开发 Java
从反射到方法句柄:深入探索Java动态编程的终极解决方案
从反射到方法句柄,Java 动态编程不断演进。方法句柄以强类型、低开销、易优化的特性,解决反射性能差、类型弱、安全性低等问题,结合 `invokedynamic` 成为支撑 Lambda 与动态语言的终极方案。
240 0
|
6月前
|
Java 开发者
Java并发编程:CountDownLatch实战解析
Java并发编程:CountDownLatch实战解析
541 100
|
6月前
|
算法 Java
Java多线程编程:实现线程间数据共享机制
以上就是Java中几种主要处理多线程序列化资源以及协调各自独立运行但需相互配合以完成任务threads 的技术手段与策略。正确应用上述技术将大大增强你程序稳定性与效率同时也降低bug出现率因此深刻理解每项技术背后理论至关重要.
446 16
|
6月前
|
NoSQL Java 关系型数据库
超全 Java 学习路线,帮你系统掌握编程的超详细 Java 学习路线
本文为超全Java学习路线,涵盖基础语法、面向对象编程、数据结构与算法、多线程、JVM原理、主流框架(如Spring Boot)、数据库(MySQL、Redis)及项目实战等内容,助力从零基础到企业级开发高手的进阶之路。
467 1
|
9月前
|
Java 数据库连接 API
2025 更新必看:Java 编程基础入门级超级完整版指南
本教程为2025更新版Java编程基础入门指南,涵盖开发环境搭建(SDKMAN!管理JDK、VS Code配置)、Java 17+新特性(文本块、Switch表达式增强、Record类)、面向对象编程(接口默认方法、抽象类与模板方法)、集合框架深度应用(Stream API高级操作、并发集合)、模式匹配与密封类等。还包括学生成绩管理系统实战项目,涉及Maven构建、Lombok简化代码、JDBC数据库操作及JavaFX界面开发。同时提供JUnit测试、日志框架使用技巧及进阶学习资源推荐,助你掌握Java核心技术并迈向高级开发。
871 5
|
监控 安全 Java
Java中的多线程编程:从入门到实践####
本文将深入浅出地探讨Java多线程编程的核心概念、应用场景及实践技巧。不同于传统的摘要形式,本文将以一个简短的代码示例作为开篇,直接展示多线程的魅力,随后再详细解析其背后的原理与实现方式,旨在帮助读者快速理解并掌握Java多线程编程的基本技能。 ```java // 简单的多线程示例:创建两个线程,分别打印不同的消息 public class SimpleMultithreading { public static void main(String[] args) { Thread thread1 = new Thread(() -> System.out.prin
|
安全 Java 调度
Java中的多线程编程入门
【10月更文挑战第29天】在Java的世界中,多线程就像是一场精心编排的交响乐。每个线程都是乐团中的一个乐手,他们各自演奏着自己的部分,却又和谐地共同完成整场演出。本文将带你走进Java多线程的世界,让你从零基础到能够编写基本的多线程程序。
167 1