多线程进阶知识篇(二)
文章目录
- 一、Synchronized 锁
- 二、ReentrantLock 锁
- 三、两阶段终止
- 阶段一:通知终止
- 阶段二:响应中断
- 四、线程池
- 为什么要使用线程池?
- 如何创建线程池?
- Executors
- ThreadPoolExecutor
- 线程池的基本参数
- 五、线程池处理任务的流程
一、Synchronized 锁
synchronized 是 Java关键字,用于修饰方法或代码块,属于重量级锁,主要是在多线程环境下实现对共享资源的互斥访问。
基本使用:
public class SynchronizedExample {public synchronized void method1() {// 修饰实例方法,锁的是当前对象实例}public static synchronized void method2() {// 修饰静态方法,锁的是当前类的 Class 对象}public void method3() {synchronized (this) {// 代码块锁,锁的是当前对象}}
}
synchronized 可以保证数据的可见性和原子性,支持可重入和自动释放锁,但是不支持超时锁和中断等操作。
二、ReentrantLock 锁
ReentrantLock 是 JDK 1.5 引入的可重入锁,属于轻量级锁,相比 synchronized 增加了超时、中断、公平锁等高级功能。
基本使用:
public class ReentrantLockExample {private final ReentrantLock lock = new ReentrantLock();public void method() {lock.lock();try {// 临界区} finally {lock.unlock(); }}
}
ReentrantLock 支持可重入、可中断、超时机制和条件变量,但是加锁需要手动释放,否则可能造成死锁。
三、两阶段终止
两阶段终止模式: 是指优雅地中止线程的方式。
阶段一:通知终止
线程通过 interrupt() 设置中断标志,告知目标线程终止。
阶段二:响应中断
线程检测到中断标志(或抛出中断异常),执行清理工作后安全退出。
class Main extends Thread {public void run() {while (!Thread.currentThread().isInterrupted()) {try {Thread.sleep(1000);} catch (InterruptedException e) {break; // 退出循环}}}}
四、线程池
为什么要使用线程池?
- 提高响应速度
- 减少资源消耗
- 易于管理线程
如何创建线程池?
Executors
- 无限线程数的线程池
ExecutorService threadPool = Executors.newCachedThreadPool();
- 固定线程的线程池
ExecutorService threadPool = Executors.newFixedThreadPool(10);
- 单一线程的线程池
ExecutorService threadPool = Executors.newSingleThreadExecutor();
ThreadPoolExecutor
ExecutorService pool = new ThreadPoolExecutor(2,5,10,TimeUnit.SECONDS,new ArrayBlockingQueue<>(10),Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy()
);
pool.execute(() -> {System.out.println(Thread.currentThread().getName() + " 执行任务:");});
pool.shutdown();
线程池的基本参数
ThreadPoolExecutor(int corePoolSize, // 核心线程数int maximumPoolSize, // 最大线程数long keepAliveTime, // 空闲线程存活时间TimeUnit unit, // 时间单位BlockingQueue<Runnable> workQueue, // 任务队列ThreadFactory threadFactory, // 线程工厂RejectedExecutionHandler handler // 拒绝策略
)
五、线程池处理任务的流程
- 如果当前线程数 < 核心线程数,则创建一个线程执行任务。
- 如果核心线程数 <= 当前线程数 < 最大线程数并且阻塞队列未满,则线程进入阻塞队列等待。
- 如果阻塞队列已满但是当前线程数 < 最大线程数,则创建一个线程执行任务。
- 如果当前线程数等于最大线程数,则根据拒绝策略处理该线程。