Java多线程核心概念与创建方式详解
本文详细解析Java多线程的核心机制,涵盖进程与线程的区别、线程生命周期及线程安全的定义。通过通俗类比帮助理解抽象概念,并重点介绍继承Thread类、实现Runnable接口及使用Callable创建线程的三种标准方式及其代码实现。
什么是线程
线程是操作系统进行CPU调度的最小执行单元,通常被称为轻量级进程。它是进程内部的实际运作单位,依赖于进程存在。一个进程中可以包含多个线程,它们共享进程的内存空间(如堆内存),但各自拥有独立的栈空间和程序计数器,用于记录各自的执行上下文。
线程的状态
在JVM中,线程的生命周期包含多种状态。常见的可见状态包括可运行状态(Runnable)和阻塞状态(Blocked)。由于CPU时间片轮转机制极短,线程在运行过程中会频繁切换。阻塞状态通常发生在等待I/O操作完成或争夺临界资源(锁)时。理解这些状态有助于分析程序的性能瓶颈和死锁问题。
通俗理解进程与线程
为了更直观地理解这两个概念,可以将“进程”比作一家餐厅。餐厅作为一个独立的实体运行,拥有自己的地址、设备和资金(独立内存空间)。餐厅内的服务员则是“线程”,他们是实际提供服务的单位。餐厅的餐桌和客户数据是共享资源。当多名服务员同时为不同顾客服务时,即为多线程并发;若争夺同一张空桌,则涉及资源竞争。而“线程池”则相当于预先培训好的一批待命服务员,随时响应客户需求,减少招聘和培训的开销。
线程与进程的区别
- 资源拥有权:进程是资源分配的基本单位,拥有独立的地址空间;线程是CPU调度的基本单位,共享所属进程的资源。
- 稳定性与隔离性:进程间逻辑隔离,一个进程崩溃通常不会影响其他进程;线程共享内存,一个线程出错可能导致整个进程崩溃。
- 开销效率:线程的创建、销毁和切换速度远快于进程,占用内存少,CPU利用率高;进程切换涉及环境重建,开销较大。
- 编程复杂度:进程间通信较为复杂,但安全性高;线程间同步需程序员手动管控(如加锁),开发难度大,容易出现竞态条件。
什么是线程安全
当多条线程并行访问共享数据时,如果代码能通过同步机制保证每次执行的结果与单线程执行一致,且不会出现数据污染或意外情况,则称为线程安全。
类比说明:在餐厅场景中,若两名服务员同时记录“下一位客人的座位号”,他们可能都读取到当前的数字“8”,然后都将其增加为“9”并分配出去,导致座位冲突。这就是典型的非线程安全问题。解决此问题需要引入互斥机制(如排号锁),确保同一时刻只有一个服务员能修改该数据。
如何创建线程
在Java中,创建线程主要有以下三种标准方式:
第1步:继承 Thread 类创建线程
目的:直接扩展Thread类并重写run方法。
注意:Java不支持多继承,因此该类无法再继承其他业务类。
package thread;
/**
* @author 香菜
*/
public class ExtendThread extends Thread {
@Override
public void run() {
System.out.println("ExtendThread");
}
}
第2步:实现 Runnable 接口
目的:将任务逻辑与线程对象分离,提高灵活性,支持多个线程共享同一个Runnable实例。
package thread;
/**
* @author 香菜
*/
public class ImpRunnable implements Runnable {
@Override
public void run() {
System.out.println("Runnable");
}
}
第3步:使用 Callable 和 FutureTask 创建线程
目的:适用于需要在线程执行结束后获取返回结果(返回值)的场景,且允许抛出受检异常。
package thread;
import java.util.concurrent.Callable;
/**
* @author 香菜
*/
public class ImpCallable implements Callable<Integer> {
@Override
public Integer call() throws Exception {
System.out.println("Callable ");
return 1;
}
}
线程启动示例
以下是上述三种方式在主线程中的调用示例:
package thread;
import java.util.concurrent.FutureTask;
/**
* @author 香菜
*/
public class MainTest {
public static void main(String[] args) {
// 方式1:继承Thread
new ExtendThread().start();
// 方式2:实现Runnable
new Thread(new ImpRunnable()).start();
// 方式3:实现Callable
new Thread(new FutureTask<>(new ImpCallable())).start();
}
}
总结
掌握线程的本质及其与进程的关系,是构建高效并发应用的基础。在实际项目开发中,理清项目的线程模型,合理选择线程创建方式并处理线程安全问题,能有效避免大部分并发故障。以上就是Java多线程核心概念与创建方式的详细内容,更多关于Java并发编程的资料请关注本站其它相关文章!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









