线程作为JVM中独立的执行单元,其生命周期遵循严格的状态机模型。通过以下 浅色背景Mermaid状态图,可清晰观测其能量跃迁轨迹:
// 线程对象初始化,未注册到调度器
Thread coreThread = new Thread(() ->
log.info("CoreThread initialized at {}", System.currentTimeMillis())
);
此时线程处于冷启动状态,JVM完成内存分配与元数据初始化,但未进入调度队列。
coreThread.start(); // 提交至JVM线程调度器
该操作触发线程元数据向操作系统内核态的传递,线程进入可运行队列(Ready Queue),等待CPU时间片分配。
当线程获取CPU时间片时,执行流进入run()
方法。在多核系统中,不同线程可并行运行于不同CPU核心,实现真正的指令级并行。
synchronized
锁等待)wait()
/join()
)sleep()
/parkNanos()
)// 锁竞争阻塞示例
synchronized (lockObj) {
// 若锁被占用,线程进入阻塞队列
}
线程执行完run()
方法或抛出未捕获异常时,进入TERMINATED状态。JVM自动释放线程栈内存,但Thread对象仍可通过引用访问(如getState()
)。
// 继承Thread类,重写run方法
public class WorkerThread extends Thread {
private final UUID taskId;
public WorkerThread(UUID taskId) {
this.taskId = taskId;
setName("Worker-" + taskId.toString().substring(0, 8));
}
@Override
public void run() {
log.debug("Task {} started on CPU core {}", taskId, Thread.currentThread().getId());
// 业务逻辑
}
}
// 启动方式
new WorkerThread(UUID.randomUUID()).start();
技术局限:受Java单继承限制,无法同时继承其他业务类,扩展性受限。
// 函数式接口实现
@FunctionalInterface
public interface Runnable {
void run();
}
// 业务场景应用
ExecutorService executor = Executors.newFixedThreadPool(4);
executor.submit(() -> {
// 无返回值的异步任务
return CompletableFuture.runAsync(() -> {
// 支持异步编排的任务体
});
});
优势特性:
// 泛型化结果返回
public interface Callable<V> {
V call() throws Exception;
}
// 异步计算示例
Future<Double> future = executor.submit(() -> {
// 耗时计算任务
return complexAlgorithm();
});
// 结果获取(支持超时控制)
Double result = future.get(10, TimeUnit.SECONDS);
技术亮点:
future.cancel(true)
)Java采用 协作式中断模型,通过以下三个核心API实现线程的优雅终止:
// 向目标线程发送中断信号
targetThread.interrupt();
该方法设置线程的中断标志位(interrupt flag),不会立即终止线程,需配合业务逻辑处理。
// 非静态方法,不清除中断标志
while (!Thread.currentThread().isInterrupted()) {
// 轮询检测中断状态
processData();
// 可中断阻塞操作
blockingQueue.take(); // 可能抛出InterruptedException
}
// 静态方法,清除当前线程中断标志
if (Thread.interrupted()) {
// 处理中断请求
shutdownHook(); // 资源释放钩子
return;
}
最佳实践:
public void run() {
try {
while (true) {
// 业务逻辑
performTask();
// 可中断的阻塞操作
TimeUnit.MILLISECONDS.sleep(100);
}
} catch (InterruptedException e) {
// 重置中断标志,允许上层调用感知中断
Thread.currentThread().interrupt();
// 执行优雅退出逻辑
log.info("Thread {} interrupted, starting shutdown", getName());
}
}
在生产环境中,应通过ExecutorService
构建线程池,实现:
getActiveCount()
)ExecutorService threadPool = new ThreadPoolExecutor(
4, // corePoolSize:核心线程数
8, // maximumPoolSize:最大线程数
30, // keepAliveTime:空闲线程存活时间
TimeUnit.SECONDS,
new LinkedBlockingQueue<>(100), // 任务队列
new ThreadFactory() { // 自定义线程工厂
private final AtomicInteger counter = new AtomicInteger(1);
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setName("PoolWorker-" + counter.getAndIncrement());
t.setDaemon(false); // 设置为用户线程
return t;
}
},
new ThreadPoolExecutor.AbortPolicy() // 拒绝策略
);
// 获取线程池状态
int activeThreads = ((ThreadPoolExecutor)threadPool).getActiveCount();
long completedTasks = ((ThreadPoolExecutor)threadPool).getCompletedTaskCount();
// 优雅关闭线程池
threadPool.shutdown();
try {
if (!threadPool.awaitTermination(60, TimeUnit.SECONDS)) {
threadPool.shutdownNow(); // 强制终止
}
} catch (InterruptedException e) {
threadPool.shutdownNow();
}
对于简单变量操作,推荐使用java.util.concurrent.atomic
包中的原子类,实现无锁化编程:
AtomicInteger counter = new AtomicInteger(0);
// 原子递增
counter.incrementAndGet();
// 条件更新(CAS操作)
counter.compareAndSet(oldValue, newValue);
// 为每个线程创建独立副本
ThreadLocal<DateFormat> dateFormatThreadLocal = ThreadLocal.withInitial(
() -> new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
);
// 使用示例
String formattedDate = dateFormatThreadLocal.get().format(new Date());
tryLock(long time, TimeUnit unit)
设置锁获取超时private volatile boolean shutdownFlag; // 标识线程是否关闭
ConcurrentHashMap
、AtomicReference
等并发组件从状态机的精密控制到线程池的集群管理,Java多线程体系构成了现代高并发系统的底层引擎。在实际开发中,需结合业务场景选择合适的线程模型,同时利用jstack
、VisualVM
等工具进行实时监控,确保线程安全与性能的平衡。
关注我的更多技术内容
如果你喜欢这篇文章,别忘了点赞、收藏和分享!有任何问题,欢迎在评论区留言讨论!
本文首发于我的技术博客,转载请注明出处