目录结构
- 了解并发和并发的价值
- 了解线程
- Java中线程的实现
- 多线程级别原理
- 线程的启动和停止
【高并发】当前系统能够同时承载的并发数(网页能够同时支持10万个用户查看,系统能支持10万请求的处理) TPS:每秒事务处理数量增删改 QPS:1000个用户同时发起查询,1000用户同时得到结果,说明QPS达到1000
如何支撑高并发?
硬件资源
- CPU:核心数:决定能够并行的任务数
- 内存:内存保存数据,提高性能
- 磁盘:SSD,机械硬盘
- 网卡:千兆,万兆 ...
软件资源
-
CPU:线程是CPU执行的最小单元,8核,同时可以运行8个线程
-
IO:和数据库交互,保存到数据库->刷到磁盘,IO性能影响查询速度,内存/缓存/异步刷盘策略;数据分库分表方式(减少数据量提升计算的性能),分布式缓存(减少IO性能的影响,非机构化数据),分布式消息中间件(异步化,先把结果告诉用户已经完成了,程序在后端处理)
-
单节点遇到瓶颈,订单放在A服务器计算,库存放在B服务器计算,软件硬件优化代理收益:QPS1000 -> QPS10000
多线程技术
什么是线程
- Java程序 -> .java源文件(磁盘) -> JVM(编译).class ->main方法运行这个程序(加载到内存中) -> 产生一个进程
- CPU来执行这个进程中的指令
- 线程是操作系统能够调度的最小单元,也是CPU能够调度的最小单元。 假设进程中,有一个从磁盘加载一个文件保存到数据库的操作。 CPU的运算效率 <-> 磁盘的IO效率,IO效率低,此时CPU处于阻塞,此时CPU资源是浪费的。 思考:当某个进程因为IO阻塞时,CPU能否切换到其他的进程来执行呢? 多道程序设计:多进程,让多个进程同时加载到内存,进程直接是相互隔离不影响。 分时系统:CPU的诗句片切换
线程 -> 轻量级进程 一个进程中 ->可以存在N个线程
- 加载磁盘 -> 分配线程执行
- 保存到数据库
- ...
单线程多线程
线程的特征
- 异步(注册 -> 发送email)
- 并行(CPU核数)
思想翻来覆去就这些
比如:读取一个大文件,读取完一起处理。分片思想:读1000,分配一个线程处理。
比如:一个系统,一个人开发需要一个月。30个人开发,需要一天。
Java中如何使用线程?
Java中使用线程特别简单
- 继承Thread(也实现了Runnable)
- 实现Runnable接口
- Callable/Future
- CompletableFuture 基于Callable/Future的优化
- dubbo,nacos等阿里系源码常用CompletableFuture 使用线程很简单直接实现接口Runnable就可以了new Thread(new SmsSenderTask()).start(),start()方法是JVM调用的,最好回调run()。
-线程不建议直接new,建议用线程池来控制线程的数量,和线程的复用。
- Java开启一个线程的最终执行过程
- 线程有什么用?哪些地方可以用?但凡涉及到你需要并行处理和异步处理的地方都可以,你可以去思考一下,你项目一定会有这样的场景,只是你没有想到。
线程的原理
线程的声明周期
线程从开始 -> 结束 start() 启动一个线程 当线程中的执行完毕后自动销毁,run()结束 线程的其他状态
- 阻塞状态,Thread.sleep()、join()、wait()、WAITING、TIME_WATING
- 锁阻塞,BLOCKED、Synchronize同步锁,因为没有抢占到锁而阻塞线程、LockSupport.park(this)阻塞
线程停止
stop方法停止线程 kill -9命令 正常情况下
interrupt()停止线程
- 线程可控时,可以自动结束时,不需要中断。
- run()方法不可控的时候,无法被自动结束的情况下,wait()、sleep()才需要终止。
- 用线程池一般不用自己中断,线程池已经封装好了
- interrupt是native 方法