一、线程基础

• 线程定义:进程内的最小执行单元,一个进程可包含多个线程,共享进程的内存空间(如堆、方法区),但有独立的栈和程序计数器。

• 线程状态:共6种,分别是NEW(新建)、RUNNABLE(可运行)、BLOCKED(阻塞)、WAITING(等待)、TIMED_WAITING(计时等待)、TERMINATED(终止),状态转换需通过start()、wait()、sleep()等方法触发。

• 创建方式:

1. 继承Thread类,重写run()方法,调用start()启动(注意:直接调用run()仅为普通方法调用,不会启动新线程)。

2. 实现Runnable接口,重写run()方法,将实例传入Thread构造器后调用start()。

3. 实现Callable接口,重写call()方法(可返回结果、抛出异常),结合FutureTask获取执行结果。

二、线程控制方法

• 启动与终止:启动必须用Thread.start(),底层调用JVM的start0()创建新线程;终止不推荐用stop()(强制终止会导致资源未释放),推荐用“标志位”(如定义volatile boolean flag,通过修改flag让线程自行退出)。

• 休眠与等待:

◦ Thread.sleep(long millis):让当前线程休眠指定时间,休眠时持有锁,时间到后进入RUNNABLE状态。

◦ Object.wait():让当前线程释放锁并进入WAITING状态,需在synchronized代码块中调用,唤醒需依赖notify()或notifyAll()。

• ** join()**:让调用该方法的线程等待当前线程执行完毕后再继续,例如threadA.join()表示“主线程等threadA执行完”。

三、线程安全

• 核心问题:多个线程并发访问共享资源时,因“指令重排序”“可见性”“原子性”问题导致结果异常。

• 解决方案:

◦ synchronized:可修饰方法(非静态锁为对象,静态锁为类)或代码块(锁为括号内的对象),保证同一时间只有一个线程进入同步代码,底层依赖“对象监视器锁”实现。

◦ volatile:修饰变量,保证变量的“可见性”(一个线程修改后,其他线程能立即看到)和“禁止指令重排序”,但不保证原子性(如i++仍需额外同步)。

◦ 并发工具类:使用java.util.concurrent包下的类,如AtomicInteger(原子类,保证i++等操作原子性)、ReentrantLock(可替代synchronized,支持公平锁、可中断等特性)。

四、线程池

• 核心作用:管理线程生命周期,避免频繁创建/销毁线程的开销,控制并发线程数量,防止资源耗尽。

• 核心参数(ThreadPoolExecutor构造器):

◦ 核心线程数(corePoolSize):线程池长期维持的最小线程数,即使空闲也不销毁。

◦ 最大线程数(maximumPoolSize):线程池能容纳的最大线程数,当核心线程忙且任务队列满时,会创建新线程直到达到该值。

◦ 空闲线程存活时间(keepAliveTime):非核心线程空闲超过该时间会被销毁。

◦ 任务队列(workQueue):用于存放等待执行的任务,如LinkedBlockingQueue(无界队列)、ArrayBlockingQueue(有界队列)。

• 常见拒绝策略:当线程池和任务队列都满时,处理新任务的方式,如AbortPolicy(默认,抛出异常)、CallerRunsPolicy(由调用者线程执行)。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐