线程
进程是操作系统进行资源分配和调度的一个独立单位,是应用程序运行的载体。
线程是调度 CPU 的最小单元,也叫轻量级进程 LWP(Light Weight Process)。
状态
new,ready,running,waiting,blocked,terminated
线程模型
- 用户级线程(ULT)
- 用户程序实现,不依赖操作系统核心,应用提供创建、同步、调度和管理线程的函数来控制用户线程。不需要用户态 / 内核态切换,速度快。内核对 ULT 无感知,线程阻塞则进程(包括它的所有线程)阻塞。
- 内核级线程(KLT)
- 系统内核管理线程(KLT),内核保存线程的状态和上下文信息,线程阻塞不会引起进程阻塞。在多处理器系统上,多线程在多处理器上并行运行。线程的创建、调度和管理由内核完成,效率比 ULT 要慢,比进程操作快。(JVM 大多使用 KLT)
Java 线程与系统内核线程
Java 线程创建是依赖于系统内核,通过 JVM 调用系统库创建内核线程,内核线程与 Java-Thread是 1::1 的映射关系。
线程池
池化思想:线程池、字符串常量池、数据库连接池
目的:提高资源的利用率
- 重用存在的线程,减少线程创建,消亡的开销,提高性能
- 提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。
-
意义
线程是稀缺资源,它的创建与销毁是一个相对偏重且耗资源的操作,而 Java 线程依赖于内核线程,,创建线程需要进行操作系统状态切换,为避免资源过度消耗需要设法重用线程执行多个任务。线程池就是一个线程缓存,负责对线程进行统一分配、调度与监控。
什么时候使用?
单个任务处理时间比较短
- 需要处理的任务数量很大
阻塞队列
- 在任意时刻,不管并发有多高,永远只有一个线程能够进行队列的入队或者出队的操作!
- 线程安全
- 有界 || 无界
- 队列满,只能进行出队操作,所有入队的操作必须等待,也就是被阻塞
队列空,只能进行入队操作,所有出队的操作必须等待,也就是被阻塞
自定义线程池
public class MyThreadPool {
public static void main(String[] args) {
/**
* public ThreadPoolExecutor(int corePoolSize, //核心线程池的大小
* int maximumPoolSize, //最多线程数
* long keepAliveTime, // 线程没有工作,最大存活时间
* TimeUnit unit, //时间单位
* BlockingQueue<Runnable> workQueue, //负荷状态下的阻塞队列
* ThreadFactory threadFactory,
* RejectedExecutionHandler handler)
*/
ExecutorService service = new ThreadPoolExecutor(3, 5, 1L, TimeUnit.SECONDS,
new ArrayBlockingQueue<>(3),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy());
for (int i = 0; i < 9; i++) {
service.execute(() -> {
System.out.println(Thread.currentThread().getName() + " ====> " + "正在办理业务");
});
}
service.shutdown();
}
}
状态
Running
ShutDown
Stop
Tidying
所有的任务已经终止,ctl 记录的 “任务数量”为 0,ctl 负责记录线程池的运行状态与活动线程数量
Terminated
线程池彻底终止,则线程池转变为 terminated 状态
```java private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0)); private static final int COUNT_BITS = Integer.SIZE - 3; //用高3位记录线程状态 //低29位记录当前工作线程数 private static final int CAPACITY = (1 << COUNT_BITS) - 1;
// runState is stored in the high-order bits private static final int RUNNING = -1 << COUNT_BITS; private static final int SHUTDOWN = 0 << COUNT_BITS; private static final int STOP = 1 << COUNT_BITS; private static final int TIDYING = 2 << COUNT_BITS; private static final int TERMINATED = 3 << COUNT_BITS;
// Packing and unpacking ctl private static int runStateOf(int c) { return c & ~CAPACITY; } private static int workerCountOf(int c) { return c & CAPACITY; } private static int ctlOf(int rs, int wc) { return rs | wc; } ```