杰瑞科技汇

进程与线程,Java中如何区分与协作?

生动的比喻:一家公司

想象一下进程就像一家完整的公司

进程与线程,Java中如何区分与协作?-图1
(图片来源网络,侵删)
  • 公司:它有自己的独立资产(内存空间)、组织架构、财务系统,它是一个独立的执行单位,可以独立地存在和运作,你可以启动它,也可以关闭它,它与其他公司是隔离的。
  • 员工:公司里的线程就像是公司的员工,他们共享公司的资源(办公室、电脑、打印机等),共同协作完成公司的目标(项目),多个员工可以同时在不同岗位上工作(比如一个程序员在写代码,一个设计师在画图)。
  • 员工之间的关系
    • 共享资源:所有员工都能使用公司的公共资源。
    • 协作:他们需要互相沟通、同步工作,不能同时使用同一个资源(比如同一台电脑),否则会出乱子,这就需要项目经理(锁、同步机制)来协调。
    • 独立性:每个员工也有自己的私人工作空间和任务(线程的栈空间),可以独立处理自己的事情。

核心区别与联系

我们把比喻转化为技术概念。

定义

  • 进程

    • 操作系统进行资源分配和调度的一个独立单位
    • 它是一个正在运行的应用程序的实例,你同时打开了两个浏览器窗口,通常就有两个浏览器进程。
    • 每个进程都拥有自己独立的内存空间、文件句柄、系统资源等。
  • 线程

    • 进程中的一个执行单元,是CPU调度的基本单位。
    • 一个进程可以包含一个或多个线程,这些线程共享该进程的资源。
    • 线程有自己的栈空间(用于存储局部变量和方法调用),但共享堆内存(用于存放对象)和文件句柄等资源。

主要区别

特性 进程 线程
根本区别 资源分配的基本单位 CPU调度的基本单位
资源占用 拥有独立的内存空间,进程间不共享内存。 共享所属进程的内存空间(堆内存、全局变量)。
开销 创建、销毁、切换的开销大,因为需要分配和回收整个内存空间。 创建、销毁、切换的开销小,因为只需操作栈空间。
通信方式 复杂,需要通过进程间通信,如管道、消息队列、共享内存等。 简单,可以直接读写共享变量(但需要注意同步问题)。
健壮性 一个进程崩溃,通常不影响其他进程,因为它们是隔离的。 一个线程崩溃,会导致整个进程崩溃(因为共享了同一个地址空间)。
数量 一个系统中通常只有几十个进程。 一个进程中可以有成百上千个线程。

密切联系

  1. 包含关系:线程是进程的一部分,一个进程是线程的容器,没有进程的线程是不存在的。
  2. 资源共享:一个进程内的所有线程共享该进程的全部资源(如内存、文件、网络连接),这是线程比进程高效的主要原因,因为它们无需进行复杂的IPC通信。
  3. 生命周期:进程的消亡会导致其所有线程的消亡,反之,一个线程的结束不会影响同一进程中的其他线程。

Java中的体现

在Java中,这种关系体现得非常清晰。

Java进程

当你运行一个Java程序时,java MyApplication,操作系统会创建一个进程来执行Java虚拟机,这个JVM进程就是你的Java应用程序的载体。

# 在终端运行一个Java程序,会创建一个进程
java -jar my-app.jar

这个进程包含了JVM本身以及你的应用程序代码。

Java线程

Java中的线程就是JVM进程中的一个执行流,Java提供了强大的多线程编程能力。

  • 主线程:当你运行Java程序时,JVM会自动创建一个主线程,它负责执行 main 方法。
  • 创建线程:你可以通过两种主要方式创建新的线程:
    1. 继承 Thread (不推荐,因为Java是单继承)
    2. 实现 Runnable 接口 (推荐,更灵活)

代码示例:

// 1. 实现 Runnable 接口
class MyTask implements Runnable {
    @Override
    public void run() {
        // 这是新线程要执行的代码
        System.out.println("Hello from thread: " + Thread.currentThread().getName());
    }
}
public class ThreadExample {
    public static void main(String[] args) {
        // main() 方法在主线程中执行
        System.out.println("Hello from main thread: " + Thread.currentThread().getName());
        // 创建一个 Runnable 任务
        MyTask task = new MyTask();
        // 创建一个 Thread 对象,并将任务传递给它
        Thread thread = new Thread(task, "My-Worker-Thread");
        // 启动线程(操作系统会创建一个新的执行流)
        thread.start();
        // 主线程继续执行自己的任务
        System.out.println("Main thread continues its work...");
    }
}

执行结果(可能不同):

Hello from main thread: main
Main thread continues its work...
Hello from thread: My-Worker-Thread

在这个例子中:

  • 整个Java程序运行在一个JVM进程中。
  • 两个线程在运行:main 线程和我们新创建的 My-Worker-Thread
  • 这两个线程共享JVM进程的堆内存,如果它们都访问同一个对象,就需要考虑同步问题(如使用 synchronized 关键字或 Lock)。

特性 进程 线程
比喻 公司 员工
单位 资源分配单位 CPU调度单位
资源 独立内存空间 共享进程内存空间
开销
通信 复杂(IPC) 简单(共享变量)
健壮性 高(一个挂,不影响其他) 低(一个挂,全盘皆输)

核心要点:

  • 进程是“房子”,线程是“房子里的人”,人共享房子的资源(客厅、厨房),但每个人有自己的房间(栈空间)。
  • 进程间的隔离性更强,更安全;线程间的通信更高效,但需要小心同步问题。
  • 在Java编程中,我们通常说的“多线程”,就是在同一个JVM进程内创建多个线程来并发执行任务,以提高CPU利用率和程序响应速度。
分享:
扫描分享到社交APP
上一篇
下一篇