基本概念
程序
是为了完成特定任务、用某种语言编写的一组指令的集合
进程
- 进程是指定运行中的程序,比如我们使用QQ,就启动了一个进程,操作系统就会为该进程分配内存空间。
- 进程是程序的一次执行过程,或是正在运行的一个程序。是动态程序: 有它自身的产生、存在、和消亡的过程。
线程
- 操作系统中可独立执行的最小单位。
- 线程由进程创建的,是进程的一个实体
- 一个进程可以拥有多个线程,它们共享进程的资源。
-
- 线程: 同一个时刻,只允许执行一个线程
- 多线程: 同一个时刻,可以执行多个线程
- 并发: 同一个时刻,多个任务交替执行,造成一种"貌似同时"的错觉,简单的说,单核cpu实现的多任务就是并发。
- 并行: 同一个时刻,多个任务同时执行。多核cpu可以实现并行

线程基本使用、线程同步、锁机制详细相关:https://blog.csdn.net/qq_47200222/article/details/123055965
拓展
线程的一些核心概念 :
- 并发执行:线程使得程序能够并发执行,即多个线程可以同时执行不同的任务或代码片段,从而提高程序的执行效率和响应性。
- 线程调度:线程调度是操作系统决定何时运行哪个线程的过程。操作系统使用调度算法来决定线程的执行顺序和时间片分配,以实现公平性和性能优化。
- 线程状态:线程可以处于不同的状态,包括就绪(Ready)、运行(Running)、阻塞(Blocked)和终止(Terminated)等。线程的状态可以随着程序的执行和操作系统的调度而变化。
- 线程间通信:线程可以通过共享内存或消息传递等方式进行通信和同步操作。线程间通信是多线程编程中常用的技术,用于实现数据共享、任务协作和数据同步等功能。
- 线程安全性:线程安全性是指在多线程环境下保证数据和资源的正确访问的性质。线程安全的代码可以在多线程环境中正确地执行,而不会出现竞态条件、死锁和数据损坏等问题。
- 线程优先级:线程可以设置优先级,用于指示线程执行的相对重要性。优先级高的线程在竞争资源时会更有可能被调度执行,但并不保证高优先级线程一定比低优先级线程先执行。
线程池
1.终极指南
【Thread】线程池的 7 种创建方式及自定义线程池
https://blog.csdn.net/sco5282/article/details/120963463
2.介绍
线程池(ThreadPool)是一种基于池化思想管理和使用线程的机制:它是将多个线程预先存储在一个"池子"内,当有任务出现时可以避免重新创建和销毁线程所带来性能开销,只需要从"池子"内取出相应的线程执行对应的任务即可。
使用线程池主要有以下优点:
- 降低资源消耗(复用线程,减少线程频繁新建、销毁等带来的开销)
- 提高响应速度
- 提高线程的可管理性
3.特别注意
线程池本身是异步的,内部线程同步执行操作。
【强制】阿里巴巴在其《Java开发手册》中也强制规定:线程资源必须通过线程池提供,不允许在应用中自行显式创建线程。
【强制】线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。
Executors 返回的线程池对象的弊端如下:
1)FixedThreadPool 和 SingleThreadPool:允许的请求队列长度Integer.MAX_VALUE,可能会堆积大量的请求,从而导致 OOM。
2)CachedThreadPool:允许的创建线程数量为 Integer.MAX_VALUE,可能会创建大量的线程,从而导致 OOM。
4.ThreadPoolExecutor执行流程
ThreadPoolExecutor 关键节点的执行流程如下:
- 当线程数小于核心线程数时,创建线程。
- 当线程数大于等于核心线程数,且任务队列未满时,将任务放入任务队列。
- 当线程数大于等于核心线程数,且任务队列已满:若线程数小于最大线程数,创建线程;若线程数等于最大线程数,抛出异常,拒绝任务。

5.使用
java
@Configuration("myThreadPool")
class ThreadPoolConfig {
//可作为配置类进行使用
private int corePoolSize = 5
private int maximumPoolSize = 10
private long keepAliveTime = 60L
@Bean
ThreadPoolExecutor creatThreadPool(){
return new ThreadPoolExecutor(corePoolSize,
maximumPoolSize,
keepAliveTime,
TimeUnit.SECONDS, //存活时间单位
new LinkedBlockingQueue<>(10),//无界任务队列,线程池的任务队列可以无限制的添加新的任务
CustomerThreadFactory("my-thread-pool") ,
ThreadPoolExecutor.CallerRunsPolicy());//拒绝机制
}
//自定义命名线程池的线程
static class CustomerThreadFactory(String name) implements ThreadFactory {
private final AtomicInteger mThreadNum = new AtomicInteger(1);
@Override
public Thread newThread(Runnable r) {
return new Thread(r, name + + mThreadNum.getAndIncrement());
}
}
}
//Service业务层使用
@Autowired
private lateinit ThreadPoolExecutor myThreadPool
fun main(){
...
asynchronousProcessData()
return
}
fun asynchronousProcessData(){
Runnable r = new Runnable() {
//内部处理逻辑为子线程
...
}
myThreadPool.execute(r) //主线程
}
spring boot使用自定义配置的线程池执行Async异步任务 - 晨曦曙光 - 博客园
协程(kotlin、go)
线程是在操作系统 进行,协程(Coroutine)是在用户空间进行的。
线程是操作系统的最小执行单元,因此协程是基于线程的,协程的创建、切换、销毁都是在某个线程中来进行的。
关键特点:
- 轻量级:协程由程序员控制,不需要像线程那样创建和维护额外的操作系统资源,因此占用的资源更少,启动和切换的开销更小。
- 协作式调度:协程采用协作式调度方式,即由协程自身主动让出执行权给其他协程。协程之间通过显式的挂起(suspend)和恢复(resume)操作进行通信和切换。
- 非抢占式:协程不会被强制中断或抢占执行,只有在协程主动挂起时才会切换到其他协程。这种特性可以有效避免竞态条件和死锁等并发编程问题。
- 状态保存和恢复:协程可以在执行过程中保存自己的状态,并在恢复执行时继续从之前的状态处开始。这使得协程可以实现复杂的控制流和异步编程模式。
使用场景:
- 协程切换成本比线程的切换成本比较低。
- 一是系统线程会占用非常多的内存空间,二是过多的线程切换会占用大量的系统时间。
- 协程并没有增加线程的数量,只是在线程的基础上通过分时复用的方式运行多个协程,而且协程的切换在用户态完成,切换的代价比线程从用户态到内核态的代价小很多。
在协程中不能调用导致线程阻塞的操作。也就是说,协程只有和异步IO结合起来,才能发挥最大的威力。
在协程中调用阻塞IO的操作处理方式:
- 在调用阻塞IO操作的时候,重新启动一个线程去执行这个操作,等执行完成后,协程再去读取结果。这其实和多线程没有太大区别。
- 对系统的IO进行封装,改成异步调用的方式,这需要大量的工作,最好寄希望于编程语言原生支持。