【JUC】JAVA线程小结

news2024/9/28 21:27:16

Java线程

  • 前言——阅读10-20分钟
    • 🎆1.创建和运行线程
      • Thread
      • Runable
      • FutureTask
      • 多个线程运行方式
    • 📣2.不同操作系统查看进程线程的方法
      • windows
      • linux
      • Java命令行
    • 🚀3.java线程运行原理
      • 栈与栈帧
      • 线程上下文切换(Thread Context Switch)
    • 👇4.常见的线程API
      • 不推荐的方法
    • 🐳5.Runable和Thread的run的区别
      • 为什么有 Thread 还要有 Runable
      • start和run的区别
    • 🍑6.sleep和yield区别
        • Sleep
        • Yield
    • 🌯7.sleep和wait区别
    • ✨8.wait和await区别
    • 📢9.Join方法
        • 为什么需要Join
    • 💞10.interrupt
      • 打断 sleep,wait,join已阻塞线程
    • 🐴11.主线程和守护线程
      • 什么是守护线程
      • 将线程设置为守护线程
    • 🤙12.操作系统线程的5种状态
    • 😜13.Java线程的6种状态
    • 本章的重点在于掌握

在这里插入图片描述

前言——阅读10-20分钟

本文仅对Java的线程使用学习做个小结,不涉及过多底层原理和锁的实现,

🎆1.创建和运行线程

Thread

  • run任务创建和start执行都由线程直接操作
// 创建线程对象
Thread t = new Thread() {
   public void run() {
	// 要执行的任务
    };
	// 启动线程
t.start();

Runable

  • 任务由Runable创建
  • 任务由Thread线程执行
  • 达到解耦目录,执行结果是一样的
Runnable runnable = new Runnable() {
	public void run(){
// 要执行的任务
	}
};
// 创建线程对象
Thread t = new Thread( runnable );
// 启动线程
t.start();

FutureTask

  • FutureTask的作用和Runable一样
  • FutureTask有返回值, Runable 无返回值
  • 可以用FutureTask task 接收线程执行的返回值
  • task.get()获取返回值
// 创建任务对象
FutureTask<Integer> task3 = new FutureTask<>(() -> {
	log.debug("hello");
	return 100;
});
// 参数1 是任务对象; 参数2 是线程名字,推荐
new Thread(task3, "t3").start();
// 主线程阻塞,同步等待 task 执行完毕的结果
Integer result = task3.get();
log.debug("结果是:{}", result);

多个线程运行方式

  • 交替执行
  • 谁先谁后,不由我们控制,由CPU决定

📣2.不同操作系统查看进程线程的方法

windows

任务管理器可以查看进程和线程数,也可以用来杀死进程

  • tasklist 查看进程
  • taskkill 杀死进程

linux

  • ps -fe 查看所有进程
  • ps -fT -p 查看某个进程(PID)的所有线程
  • kill 杀死进程
  • top 按大写 H 切换是否显示线程
  • top -H -p 查看某个进程(PID)的所有线程

Java命令行

  • jps 命令查看所有 Java 进程
  • jstack 查看某个 Java 进程(PID)的所有线程状态
  • jconsole 来查看某个 Java 进程中线程的运行情况(图形界面)

jconsole 远程监控配置

  • 需要以如下方式运行你的 java 类
java -Djava.rmi.server.hostname=`ip地址` -Dcom.sun.management.jmxremote -
Dcom.sun.management.jmxremote.port=`连接端口` -Dcom.sun.management.jmxremote.ssl=是否安全连接 -
Dcom.sun.management.jmxremote.authenticate=是否认证 java类
  • 修改 /etc/hosts 文件将 127.0.0.1 映射至主机名

如果要认证访问,还需要做如下步骤

  • 复制 jmxremote.password 文件
  • 修改 jmxremote.password 和 jmxremote.access 文件的权限为 600 即文件所有者可读写
  • 连接时填入 controlRole(用户名),R&D(密码

🚀3.java线程运行原理

栈与栈帧

Java Virtual Machine Stacks (Java 虚拟机栈)
我们都知道 JVM 中由堆、栈、方法区所组成,其中栈内存是给谁用的呢?其实就是线程,每个线程启动后,虚拟机就会为其分配一块栈内存。

  • 每个栈由多个栈帧(Frame)组成,对应着每次方法调用时所占用的内存
  • 每个线程只能有一个活动栈帧,对应着当前正在执行的那个方法

线程上下文切换(Thread Context Switch)

因为以下一些原因导致 cpu 不再执行当前的线程,转而执行另一个线程的代码

  • 线程的 cpu 时间片用完
  • 垃圾回收
  • 有更高优先级的线程需要运行
  • 线程自己调用了 sleep、yield、wait、join、park、synchronized、lock 等方法

当 Context Switch 发生时,需要由操作系统保存当前线程的状态,并恢复另一个线程的状态,Java 中对应的概念就是程序计数器(Program Counter Register),它的作用是记住下一条 jvm 指令的执行地址,是线程私有的

  • 状态包括程序计数器、虚拟机栈中每个栈帧的信息,如局部变量、操作数栈、返回地址等
  • Context Switch 频繁发生会影响性能

开启IDEA的debugger模式,这里每一行对应一个栈帧

  • read方法
  • main方法
  • 先进后出,先运行的在栈底

图片.png
一个线程对应一个方法栈

  • 线程t1和t2

图片.png

👇4.常见的线程API

图片.png图片.png图片.png图片.png

不推荐的方法

图片.png

🐳5.Runable和Thread的run的区别

  1. 通过组合的方式调用run,从源码角度实际都是同一个run方法
  • 源码中Runable重载run,再传参给Thread,在Thread的中判断 Runable 不空,优先调用 Runable 的方法
  • 否则就是Thread的run方法,但其实Runable的run方法的内部还是Thread的run方法
  1. 直接在Thread重载run方法,则运行时运行重载的方法

为什么有 Thread 还要有 Runable

因为有的场景下我们需要把任务和执行两者分开解耦

  • Thread创建run任务并start执行,任务和执行都耦合在Thread对象中
  • Runable用来创建任务,以传参的方式将 Runable所带的任务传入Thread,然后让Thread执行就实现了任务和执行的解耦

有人会问什么情况下需要这种分离的玩意?

  • 消息队列: 生产者消费者就是执行者,队列里面的就是任务
  • 凡是需要创建任务和执行任务分离的场景,都可以尝试使用进行解耦

start和run的区别

  1. 直接调用 run 是在主线程中执行了 run,没有启动新的线程
  2. 使用 start 是启动新的线程,通过新的线程间接执行 run 中的代码
  3. start并不会马上执行,只是让线程进入就绪态,只有他抢到CPU才能执行

🍑6.sleep和yield区别

Sleep
  1. 调用 sleep 会让当前线程从 Running 进入 Timed Waiting 状态(阻塞)
  2. 其它线程可以使用 interrupt 方法打断正在睡眠的线程,这时 sleep 方法会抛出 InterruptedException
  3. 睡眠结束后的线程未必会立刻得到执行,而是进入 Runnable 就绪状态
  4. 建议用 TimeUnit 的 sleep 代替 Thread 的 sleep 来获得更好的可读性
  5. 不会释放锁,只跟线程相关
Yield
  1. 调用 yield 会让当前线程从 Running 进入 Runnable 就绪状态,然后调度执行其它线程
    2. 具体的实现依赖于操作系统的任务调度器

🌯7.sleep和wait区别

  • 涉及到锁,此篇只涉及线程,在后篇补充

✨8.wait和await区别

  • 涉及到锁,此篇只涉及线程,在后篇补充

📢9.Join方法

为什么需要Join
  • 因为多线程是并发执行的,每个执行完成的顺序是不能确定的。
  • 意思如果有线程调用 t2.join()并运行到t2.join()这个位置会阻塞,直到t2线程执行结束,当前线程才能继续往下执行
private static void test2() throws InterruptedException {
	Thread t1 = new Thread(() -> {
		sleep(1);
		r1 = 10;
	});
	Thread t2 = new Thread(() -> {
		sleep(2);
		r2 = 20;
	});
	long start = System.currentTimeMillis();
	t1.start();
	t2.start();
	t1.join();---- // 运行到此卡住,直到t1执行完
	t2.join();-----// 运行到此卡住, 直到t2执行完
	long end = System.currentTimeMillis();
	log.debug("r1: {} r2: {} cost: {}", r1, r2, end - start);
}

💞10.interrupt

interrupt打断线程分两种情况:

  • 打断正常运行的线程
  • 打断sleep,wait,join 已阻塞线程

打断 sleep,wait,join已阻塞线程

首先声明不使用stop()打断线程的原因

  • stop()打断线程会直接杀死线程,不会给线程释放锁dd料理后事的机会
  • 资源得不到释放

如下例子就是可以处理后事线程

  • sleep,wait,join在这里可以看成是一样的阻塞态
  • (当然三者的阻塞肯定在细节上有不同,但是这里只要是阻塞就行了)
class TPTInterrupt {
        private Thread thread;
        public void start(){
            thread = new Thread(() -> {
                while(true) {
                    Thread current = Thread.currentThread();
                    if(current.isInterrupted()) {
                        log.debug("料理后事");
                        break;
                    }
                    try {
                        Thread.sleep(1000);
                        log.debug("将结果保存");
                    } catch (InterruptedException e) {
                        current.interrupt();

                    }
// 执行监控操作
                }
            },"监控线程");
            thread.start();
        }
        public void stop() {
            thread.interrupt();
        }
    }
    
--------------------------------------------------


TPTInterrupt t = new TPTInterrupt();
t.start();
Thread.sleep(3500);
log.debug("stop");
t.stop();

主要依赖这三个函数的特点"处理后事"

  • 因为sleep,wait,join也会设置打断标记
  • 而处理后事的判断条件就是打断标记
  • 通过这个标记来手动做return结束线程
  • 而不是直接stop杀死进程

图片.png图片.png

🐴11.主线程和守护线程

什么是守护线程

  • 默认情况下,Java 进程需要等待所有线程都运行结束,才会结束。
  • 有一种特殊的线程叫做守护线程,只要其它非守护线程运行结束了,即使守护线程的代码没有执行完,也会强制结束。

比如

  • 垃圾回收器线程就是一种守护线程
  • Tomcat 中的 Acceptor 和 Poller 线程都是守护线程,所以 Tomcat 接收到 shutdown 命令后,不会等待它们处理完当前请求,直接结束

将线程设置为守护线程

Thread t1 = new Thread(() -> {
log.debug("开始运行...");
sleep(2);
log.debug("运行结束...");
}, "daemon");
// 设置该线程为守护线程
t1.setDaemon(true);----------//设置为守护线程
t1.start();

🤙12.操作系统线程的5种状态

图片.png

😜13.Java线程的6种状态

图片.png

  • NEW 线程刚被创建,但是还没有调用 start() 方法
  • RUNNABLE 当调用了 start() 方法之后,注意,Java API 层面的 RUNNABLE 状态涵盖了 操作系统 层面的【可运行状态】、【运行状态】和【阻塞状态】(由于 BIO 导致的线程阻塞,在 Java 里无法区分,仍然认为是可运行)
  • BLOCKED , WAITING , TIMED_WAITING 都是 Java API 层面对【阻塞状态】的细分,后面会在状态转换详述
  • TERMINATED 当线程代码运行结束

本章的重点在于掌握

  • 线程创建
  • 线程重要 api,如 start,run,sleep,join,interrupt 等
  • 线程状态
  • 应用方面
    • 异步调用:主线程执行期间,其它线程异步执行耗时操作
    • 提高效率:并行计算,缩短运算时间
    • 同步等待:join
    • 统筹规划:合理使用线程,得到最优效果
  • 原理方面
    • 线程运行流程:栈、栈帧、上下文切换、程序计数器
    • Thread 两种创建方式 的源码
  • 模式方面
    • 终止模式之两阶段终止
  • 6种状态

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1379338.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

word写标书的疑难杂症总结

最近在解决方案工作&#xff0c;与office工具经常打交道&#xff0c;各种问题&#xff0c;在此最下记录&#xff1a; 1.word中文档距离文档顶端有距离调整不了 1.疑难杂症问题1&#xff0c;多个空格都是不能解决 #解决办法&#xff1a;word中--布局-下拉框---“版式”--“垂直…

机器人持续学习基准LIBERO系列5——获取显示深度图

0.前置 机器人持续学习基准LIBERO系列1——基本介绍与安装测试机器人持续学习基准LIBERO系列2——路径与基准基本信息机器人持续学习基准LIBERO系列3——相机画面可视化及单步移动更新机器人持续学习基准LIBERO系列4——robosuite最基本demo 1.更改环境设置 LIBERO-master/l…

MagnificAI的爆火之下 - AI时代,伟大的公司只需要2个人

这两天&#xff0c;Magnific AI又被推上风口浪尖。 起因是他们发布了全新的功能&#xff1a;将任何图像放大并增强至10,000 x 10,000 像素。 传说中的4K超清&#xff0c;也就4096像素&#xff0c;但是Magnific AI可以将一张600像素糊成智障的图片&#xff0c;几分钟的时间&…

Springboot基层健康医院云HIS信息系统源码

基层卫生健康云HIS系统采用云端SaaS服务的方式提供&#xff0c;使用用户通过浏览器即能访问&#xff0c;无需关注系统的部署、维护、升级等问题&#xff0c;系统充分考虑了模板化、配置化、智能化、扩展化等设计方法&#xff0c;覆盖了基层医疗机构的主要工作流程&#xff0c;能…

近视的孩子用什么灯?学生考研护眼台灯推荐

随着时代快速发展&#xff0c;2022年我国近视人数达到了7亿&#xff0c;呈现低龄化趋势&#xff0c;儿童及青少年人数占了53.8%。现在学业负担都很重&#xff0c;每个家长都不希望自己的孩子近视或加深近视了&#xff0c;都会想尽一切办法保护视力。而护眼台灯就成了家长购买台…

不同activity项目创建时的区别

在 Android Studio 中创建项目时&#xff0c;可以选择创建不同类型的 Activity 作为应用程序的入口点。其中&#xff0c;包括 Empty Activity、Basic Activity、Empty Compose Activity 和 Basic Compose Activity 四种类型。 Empty Activity&#xff1a;这是最简单的 Activity…

agilent n9344c频谱分析仪20ghz

181/2461/8938产品概述&#xff1a; Agilent安捷伦N9344C手持频谱分析仪20GHz Agilent安捷伦N9344C手持频谱分析仪是当今最先进的频谱分析仪器之一&#xff0c;可以在20GHz的范围内对信号进行快速、准确的分析。它不仅具有出色的性能&#xff0c;还具有紧凑的外观和轻便的重量…

分享一个使用python FastApi创建服务的简易模版,与使用http/python请求

这个博客分享一个fastapi的模版&#xff0c;并提供使用http/python访问的示例程序 文章目录 示例程序FastApi应用程序HTTP请求Python请求 示例程序 FastApi应用程序 下面是一个示例&#xff1a; 默认开启一个可以使用Get请求访问的URL&#xff1a;/example_connect这个请求有…

2024年1月12日:清爽无糖rio留下唇齿之间的香甜

友利奈绪的时间管理 2024年1月12日08:02:28进行java程序设计的上课准备 2024年1月12日08:02:44知道java的题目有18道 2024年1月12日08:43:07随机数去重比较 2024年1月12日08:54:03C语言题目最小公倍数 2024年1月12日08:58:37C语言题目二维数组变一维数组 2024年1月12日10…

2024.1.11每日一题

LeetCode 2645.构造有效字符串的最少插入数 2645. 构造有效字符串的最少插入数 - 力扣&#xff08;LeetCode&#xff09; 题目描述 给你一个字符串 word &#xff0c;你可以向其中任何位置插入 “a”、“b” 或 “c” 任意次&#xff0c;返回使 word 有效 需要插入的最少字…

SQL性能分析-整理

昨日对MySQL的索引整理了一份小文档&#xff0c;对结构/分类/语法等做了一个小总结&#xff0c;具体文章可点击&#xff1a;MySQL-索引回顾&#xff0c;索引知识固然很重要&#xff0c;但引入运用到实际工作中更重要。 参考之前的文章&#xff1a;SQL优化总结以及参考百度/CSDN…

【java八股文】之JVM基础篇

1、Java中都有哪些引用&#xff1f; 强引用 &#xff1a;发生GC时候不会被回收 软引用&#xff1a;发生内存满&#xff08;内存溢出的时候&#xff09;会被回收&#xff08;通常用于缓存&#xff09; 弱引用&#xff1a;发生下一次GC时候会被回收 虚引用&#xff1a;无法通过虚…

简单明了,汽车级LM317系列LM317D2TR4G线性电压稳压器电源设计-参数应用方案分享

低压差线性稳压器&#xff08;LDO&#xff09;&#xff0c;是指一种具有恒定电流输出电压的装置&#xff0c;主要由输入变压器、整流器、输出变压器三部分构成&#xff0c;工业原理为将输入的交流电压经过整流、滤波后得到直流输出电压&#xff0c;再经过控制元件和开关器件将稳…

web前端算法简介之队列

队列 队列基本操作 入队&#xff08;enqueue&#xff09;&#xff1a;将元素添加到队列的尾部。出队&#xff08;dequeue&#xff09;&#xff1a;从队列的头部移除元素。队首&#xff08;front&#xff09;&#xff1a;获取队列头部的元素&#xff0c;但不移除它。队尾&#x…

STM32H5培训(二)性能提升与功耗优化

文章目录 1. 前言2. 性能提升3. 功耗优化参考&#xff1a; 1. 前言 本篇主要介绍STM32H5系列的性能提升和功耗优化方面的具体表现。H5系列相比于F4系列在性能和功能上有较大的升级&#xff0c;包括更强的内核、更高的主频、更快的flash访问速度、更丰富的通信接口和先进的安全…

word2003图片不显示

如图&#xff0c;可以看出图片内容空白&#xff0c;只剩下图片边框了。这种原因是在视图选项中勾选了显示图片窗按钮&#xff0c;才会这样。 解决方法是&#xff0c;如图&#xff0c;选择打开工具菜单下的选项窗口&#xff0c;然后在选项窗口中选择视图标签&#xff0c;然后…

PyTorch安装教程(Win10),含遇到的问题及解决办法

1. 环境准备 首先&#xff0c;打开PyTorch官网&#xff1a;https://pytorch.org/get-started/locally/ 向下可以看到有如下几个条件&#xff1a; Python&#xff1a;PyTorch仅支持Python3.x&#xff0c;不支持Python2.x&#xff1b; Package Manager&#xff1a; Anaconda&am…

kubebuilder+code-generator开发k8s的controller

本文记录用kubebuilder和code-generator开发k8s的crd控制器。 概览 和k8s.io/code-generator类似&#xff0c;是一个码生成工具&#xff0c;用于为你的CRD生成kubernetes-style API实现。区别在于&#xff1a; Kubebuilder不会生成informers、listers、clientsets&#xff0c…

nodejs 版本为node-v16.14.0-x64的安装及环境变量配置

大家好&#xff0c;又见面了&#xff0c;我是你们的朋友全栈君。 第一步 安装node包 地址建议去阿里云 nodejs-release-v16.14.0安装包下载_开源镜像站-阿里云 在这里插入图片描述 安装地址在D盘下的nodejs文件夹 全部默认安装&#xff0c;一直next直到安装结束 在这里插…

js 中 复杂json 组装 实例通用模式

js 中 复杂json 组装 实例 目录概述需求&#xff1a; 设计思路实现思路分析1.js 中 复杂json 组装 实例2.js 中 复杂json 动态 组装 实例3.嵌套数组 参考资料和推荐阅读 ) Survive by day and develop by night. talk for import biz , show your perfect code,full busy&…