1、线程、进程概念理解
线程
- 线程是cpu独立运行和独立调度的基本单位
- 线程可以理解为是操作系统中的应用程序(一段代码)
- 线程是进程中一段可以单独执行的代码,线程可共享进程的内存空间
进程
- 进程是资源分配的基本单位
- 进程可以理解为操作系统
- 当一个程序被加载到内存并且被执行的时候这个程序就成为一个进程(运行中的程序)
线程调度
- 线程获得cpu时间片,线程才能够执行
- 线程优先级不同,采用抢占式调度机制,优先级相同时,采用分时调度机制。
java线程与原生操作系统线程有直接的映射关系
2、线程创建
- 继承Thread类
- 实现Runnable接口(一般建议)
- 实现Callable接口(有返回值)
- 基于线程池
由于java类的单继承特性,第一种方式局限性较大,一般建议使用第二种方式创建线程。
3、线程的生命周期
- 新建状态(new)
- 当程序new了一个线程之后,线程处于新建状态,JVM为其分配内存并初始化。
- 就绪状态(Runnable)
- 线程对象调用start()方法之后,线程处于就绪状态,等待cpu调度运行。
- 运行状态(Running)
- 线程获取cpu时间片,执行run()方法的线程执行体。
- 阻塞状态(Blocked)
- 线程因某种原因放弃cpu使用权,让出世间片,暂时停止运行。
- 阻塞情况分为三种:等待阻塞、同步阻塞、其他阻塞
- 等待阻塞:运行状态的线程执行O.wait()方法,JVM会将该线程放入等待队列。
- 同步阻塞:运行状态的线程在获取对象同步锁时,该锁被其他线程所占用,JVM会将该线程给放入锁池中
- 其他阻塞:运行状态的线程执行T.sleep()方法或者join()方法或者发出I/O请求时,JVM会将该线程置为阻塞状态,当以上情况结束时,线程重新转入就绪状态
- 死亡状态(Dead)
- 线程正常结束
- 线程异常结束
- 调用线程的stop()方法
- 该方法通常容易造成死锁,不推荐使用
4、线程相关的基本方法
wait、notify、notifyAll、sleep、join、yield等
- wait 线程等待
- 释放锁资源
- 属于Object类
- sleep 线程睡眠
- 不会释放锁资源
- 属于Thread类
- yield 线程让步
- 让出时间片资源
- 重新竞争cpu时间片
- interrupt 线程中断
- 给线程一个通知信号,影响线程内部中断标识位,线程并不会因此而改变状态
- 调用interrupt方法在线程的run方法内部可以根据isInterrupt()的值优雅的终止线程
- join 等待其他线程终止
- 可以理解为插入其他线程
- 当前线程转为阻塞状态、等待另一个线程结束,转为就绪状态,等待cpu调度
- 一般用于主线程需要子线程的返回结果时使用
- notify 唤醒线程
- 属于Object类
- 唤醒具有随机性
- notifyAll 唤醒全部线程
- 唤醒具有顺序性
- 其他方法
5、线程池
线程池化技术
-
优势
- 降低资源消耗:通过重复利用已创建的线程,降低线程创建和销毁的资源消耗
- 提高响应速度:当任务到达时,可以不需要等待线程的创建立即执行
- 提高线程的可管理性:对线程统一分配、监控、调优等
-
组成
- 线程池管理器:用于创建并管理线程池
- 工作线程:线程池中的线程
- 任务接口:每个任务必须实现的接口、用于工作线程调度运行
- 任务队列:用于存放待处理的任务,提供一种缓冲机制
-
4种线程池
线程池的顶级接口为Executor,严格意义来讲其并不是一个线程池,而是一个执行工具。真正的线程池接口为ExecutorService
- newSingleThreadExecutor
- newFixedThreadPool
- newCachedThreadPool
- newScheduledThreadPool
-
线程池不允许使用Executors去创建
线程池不允许使用Executors去创建,而是通过ThreadPoolExecutor的方式,这样的处理方式更加明确线程池的运行规则,规避资源耗尽的风险
Executors返回的线程池对象的弊端如下
- FixedThreadPool 和 SingleThreadPool
- 允许的请求队列(底层实现是LinkedBlockingQueue)长度为Integer.MAX_VALUE,可能会堆积大量的请求,从而导致OOM
- CachedThreadPool 和 ScheduledThreadPool
- 允许的创建线程数量为Integer.MAX_VALUE,可能会创建大量的线程,从而导致OOM。
- FixedThreadPool 和 SingleThreadPool
-
创建线程池
protected ScheduledExecutorService scheduledExecutorService() { return new ScheduledThreadPoolExecutor(corePoolSize, new BasicThreadFactory.Builder().namingPattern("schedule-pool-%d").daemon(true).build()) { @Override protected void afterExecute(Runnable r, Throwable t) { super.afterExecute(r, t); /*线程执行完干点什么*/ } }; }
ScheduledThreadPoolExecutor底层
-
线程池基本参数
- corePoolSize:核心线程数量,会一直存在,除非allowCoreThreadTimeOut设置为true
- maximumPoolSize:线程池允许的最大线程池数量
- keepAliveTime:线程数量超过corePoolSize,空闲线程的最大超时时间。
- unit:超时时间单位
- workQueue:工作队列,保存未执行的Runnable任务
- threadFactory:创建线程的工厂类
- handler:当线程已满,工作队列也满了的时候,会被调用。被用来实现各种拒绝策略。