并发编程-线程的作用和停止

358 阅读4分钟

目录结构

  • 了解并发和并发的价值
  • 了解线程
  • Java中线程的实现
  • 多线程级别原理
  • 线程的启动和停止

【高并发】当前系统能够同时承载的并发数(网页能够同时支持10万个用户查看,系统能支持10万请求的处理) TPS:每秒事务处理数量增删改 QPS:1000个用户同时发起查询,1000用户同时得到结果,说明QPS达到1000

如何支撑高并发?

硬件资源

  1. CPU:核心数:决定能够并行的任务数
  2. 内存:内存保存数据,提高性能
  3. 磁盘:SSD,机械硬盘
  4. 网卡:千兆,万兆 ...

软件资源

  1. CPU:线程是CPU执行的最小单元,8核,同时可以运行8个线程

  2. IO:和数据库交互,保存到数据库->刷到磁盘,IO性能影响查询速度,内存/缓存/异步刷盘策略;数据分库分表方式(减少数据量提升计算的性能),分布式缓存(减少IO性能的影响,非机构化数据),分布式消息中间件(异步化,先把结果告诉用户已经完成了,程序在后端处理)

  3. 单节点遇到瓶颈,订单放在A服务器计算,库存放在B服务器计算,软件硬件优化代理收益:QPS1000 -> QPS10000

多线程技术

什么是线程

  1. Java程序 -> .java源文件(磁盘) -> JVM(编译).class ->main方法运行这个程序(加载到内存中) -> 产生一个进程
  2. CPU来执行这个进程中的指令
  3. 线程是操作系统能够调度的最小单元,也是CPU能够调度的最小单元。 假设进程中,有一个从磁盘加载一个文件保存到数据库的操作。 CPU的运算效率 <-> 磁盘的IO效率,IO效率低,此时CPU处于阻塞,此时CPU资源是浪费的。 思考:当某个进程因为IO阻塞时,CPU能否切换到其他的进程来执行呢? 多道程序设计:多进程,让多个进程同时加载到内存,进程直接是相互隔离不影响。 分时系统:CPU的诗句片切换

线程 -> 轻量级进程 一个进程中 ->可以存在N个线程

  • 加载磁盘 -> 分配线程执行
  • 保存到数据库
  • ... 单线程多线程 image.png

线程的特征

  • 异步(注册 -> 发送email)
  • 并行(CPU核数) 思想翻来覆去就这些 比如:读取一个大文件,读取完一起处理。分片思想:读1000,分配一个线程处理。 比如:一个系统,一个人开发需要一个月。30个人开发,需要一天。 image.png

image.png

Java中如何使用线程?

Java中使用线程特别简单

  • 继承Thread(也实现了Runnable)
  • 实现Runnable接口
  • Callable/Future
  • CompletableFuture 基于Callable/Future的优化
  • dubbo,nacos等阿里系源码常用CompletableFuture 使用线程很简单直接实现接口Runnable就可以了new Thread(new SmsSenderTask()).start(),start()方法是JVM调用的,最好回调run()。

-线程不建议直接new,建议用线程池来控制线程的数量,和线程的复用。

  • Java开启一个线程的最终执行过程 image.png
  • 线程有什么用?哪些地方可以用?但凡涉及到你需要并行处理和异步处理的地方都可以,你可以去思考一下,你项目一定会有这样的场景,只是你没有想到。

线程的原理

线程的声明周期

线程从开始 -> 结束 start() 启动一个线程 当线程中的执行完毕后自动销毁,run()结束 线程的其他状态

  • 阻塞状态,Thread.sleep()、join()、wait()、WAITING、TIME_WATING
  • 锁阻塞,BLOCKED、Synchronize同步锁,因为没有抢占到锁而阻塞线程、LockSupport.park(this)阻塞

线程停止

stop方法停止线程 kill -9命令 正常情况下

interrupt()停止线程

  • 线程可控时,可以自动结束时,不需要中断。
  • run()方法不可控的时候,无法被自动结束的情况下,wait()、sleep()才需要终止。
  • 用线程池一般不用自己中断,线程池已经封装好了
  • interrupt是native 方法 image.png image.png