掘金 后端 ( ) • 2024-04-03 15:39

JUC概念

概念:JUC实际上就是我们对于jdk中java.util.concurrent 工具包的简称。它是Java SE 5.0中引入的一个全新的包,这个包下是处理并发的工具类、还有提供了线程池、异步 IO 和轻量级任务框架

JUC具体提供了什么:

  • 并发集合:如ConcurrentHashMapCopyOnWriteArrayListCopyOnWriteArraySet等,这些集合提供了比传统集合更好的并发性能。
  • 同步工具类:如SemaphoreCyclicBarrierCountDownLatchExchanger等,这些工具类提供了线程间的同步机制,使得线程间的协作更加方便。
  • 锁机制ReentrantLockReentrantReadWriteLock等,提供了比synchronized关键字更灵活的锁机制。
  • 线程池ExecutorServiceThreadPoolExecutor等,提供了线程池的实现,可以有效地管理线程的创建和销毁,提高资源利用率。
  • 原子变量AtomicIntegerAtomicLongAtomicReference等,提供了无锁的线程安全操作,用于实现高效的原子操作。
  • 并发任务执行FutureCallable接口,以及ExecutorServicesubmit方法,使得异步执行任务和处理结果更加简单。
  • 并发集合操作ConcurrentNavigableMap等,提供了线程安全的集合操作,可以在多线程环境下安全地进行数据的插入、删除和查询。
  • 条件变量Condition接口,提供了线程间的等待/通知机制,使得线程间的协调更加灵活。

并行和并发

并发:多线程操作同一个资源,并发编程的本质就是充分利用CPU的资源,是同一时间应对(dealing with)多件事情的能力 并行:(多个人一起行走) CPU 多核 ,多个线程可以同时执行,是同一时间动手做(doing)多件事情的能力

多线程一定可以提高程序运行效率吗?

  1. 单核 cpu 下,多线程不能实际提高程序运行效率,只是为了能够在不同的任务之间切换
  2. 多核 cpu 可以并行跑多个线程,但能否提高程序运行效率还是要分情况的

进程、线程

程序由指令和数据组成,但这些指令要运行,数据要读写,就必须将指令加载至 CPU,数据加载至内存。在 指令运行过程中还需要用到磁盘、网络等设备。

进程就是用来加载指令、管理内存、管理 IO 的。当一个程序被运行,从磁盘加载这个程序的代码至内存,这时就开启了一个进程。进程就可以视为程序的一个实例。大部分程序可以同时运行多个实例进程(例如记事本、画图、浏览器等),也有的程序只能启动一个实例进程(例如网易云音乐、360 安全卫士等)

而一个进程之内可以分为一到多个线程,一个线程就是一个指令流,将指令流中的一条条指令以一定的顺序交给 CPU 执行。

总结一下:

进程:系统进行资源分配和调度的基本单位,可以说是一个程序,QQ.exe Music.exe 程序的集合,每⼀个进程都有它自己的内存空间和系统资源 线程:操作系统能够进行运算调度的最小单位,它被包含在进程之 中,是进程中的实际运作单位,并且共享进程资源(如内存空间、文件句柄)

创建线程的几种方式

  • 通过实现Runnable接口来创建Thread线程
  • 通过继承Thread类来创建一个线程
  • 通过FutureTask接口接收 Callable 类型的参数
  • 通过线程池

image.png

其中使用Runnable :

  • Thread是把线程和任务合并在了一起,Runnable是把线程和任务分开了
  • 用 Runnable 更容易与线程池等高级 API 配合
  • 用 Runnable 让任务类脱离了 Thread 继承体系,更灵活

查看运行中线程方式

java jps 命令查看所有 Java 进程

jstack 查看某个 Java 进程(PID)的所有线程状态

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

用户线程和守护线程

用户线程:用户实现、不需要操作系统内核支持

守护线程:程序运行的时候在后台提供一种通用服务的线程,用来服务于用户线程,比如垃圾回收线程

可以通过thread.setDaemon将线程设置为守护线程,设置守护线程,需要在start()方法之进行

Java默认:mian 线程、GC 线程

线程运行原理

JVM中的每个线程在创建后都会被分配一个独立的栈内存。这个栈内存用于存储与线程执行相关的信息,如局部变量、方法调用的参数和返回值、以及方法调用的上下文。每个线程的栈由多个栈帧组成,每个栈帧对应一次方法调用。线程在执行过程中,当前活动的栈帧代表了正在执行的方法。

线程生命周期

  • new新建:线程对象刚被创建,但还没有start方法
  • Runnable运行态:当线程调用了start方法正在等待运行或者正在执行时
  • Blocked阻塞:就是一个线程想获取一个锁,但是这个锁被其他对象持有
  • Waiting无限等待:一个线程等待另一个线程执行一个(唤醒)动作
  • Teminated被终止:run方法正常退出或者因为某些原因退出时