如何简单的去使用jconsloe 查看线程 (多线程编程篇1)

目录

 前言

1.进程和线程

进程

PCB 的作用

并发编程和并行编程

线程

为什么选择多线程编程

2.在IDEA中如何简单创建一个线程 

1. 通过继承Thread类

2. 通过实现 Runnable 接口

3. 使用 Lambda 表达式

3.如何简单使用jconsloe去查看创建好的线程

结尾 

线程的优点

进程和线程的区别

 前言

2025来了,这是第一篇博客,算是笔者的学习笔记吧,供和我一样的初学读者参考学习,愿我们一同进步!

本篇博客大致简单地讨论如下内容:

1.什么是线程,什么是进程?

2.在IDEA中如何简单创建一个线程

3.如何简单使用jconsloe去查看创建好的线程

如果对您有帮助,希望您可以点赞收藏,如果您发现有错误的地方请私信笔者,谢谢大家!!!

1.进程和线程

进程

首先是进程,在笔者的理解中,进程可以简单形容为‘正在运行中的程序’。操作系统通过创建和管理进程来分配和控制硬件资源,确保每个进程能够独立地执行并共享计算机的资源.

这里我们引入一个概念:

为了更好地管理每一个进程,操作系统为每个进程分配一个特殊的数据结构,叫做 PCB ,即进程控制块,是操作系统用于管理进程的一个数据结构。它保存了关于进程的重要信息,使得操作系统能够有效地管理和调度进程。每个进程在创建时,操作系统都会为其分配一个 PCB,并在进程的生命周期内持续维护它。

按照笔者的理解,pcb中有许多属性,存储了进程的信息,操作系统也通过pcb来管理我们的进程

PCB的具体作用如下

PCB 的作用

  1. 存储进程状态

    • PCB 保存了进程的状态信息(如运行中、就绪、阻塞等),帮助操作系统了解进程的当前执行状态。
    • 进程的状态变化(如从就绪状态到运行状态)时,操作系统会更新 PCB。
  2. 保存程序计数器

    • 程序计数器(Program Counter)保存了进程下一条将要执行的指令的地址。每次进程被切换时,操作系统会保存当前进程的程序计数器,并恢复下一个进程的程序计数器。
  3. 保存CPU寄存器内容(与2合称为上下文)

    • 当进程被暂停时,CPU 寄存器中的数据(如通用寄存器、堆栈指针等)会被保存到 PCB 中。下次该进程被调度时,操作系统会恢复这些寄存器内容,确保进程从上次暂停的地方继续执行。
  4. 存储内存管理信息

    • PCB 包含与进程地址空间相关的信息,如进程的内存分配、页表信息等。它帮助操作系统进行内存管理,确保进程在自己的地址空间内运行,并避免不同进程之间的内存冲突。
  5. 存储进程调度信息(优先级)

    • PCB 中保存了调度信息(如优先级、调度策略等),这些信息用于进程的调度和优先级判断,帮助操作系统决定哪个进程在何时被调度执行。
  6. 保存进程标识符(PID)

    • 每个进程都有一个唯一的进程标识符(PID)。操作系统通过 PID 来识别不同的进程。PCB 中包含了进程的 PID。
  7. 记录进程的资源使用情况(记账信息)

    • PCB 中还保存了进程所拥有的资源信息,比如文件描述符、I/O 设备等资源。这些信息对操作系统在资源分配和回收时非常重要。

通过了解可以发现,每个进程在创建时,操作系统都会为其分配一个独立的 PCB(进程控制块)。正是因为 PCB 中保存了进程的状态信息、资源信息、调度信息等,操作系统才能够独立管理每一个进程。

也因此,进程成为了操作系统进行资源分配和调度管理的基本单位

并发编程和并行编程

在介绍线程之前,简单介绍一下并发,并行编程

  • 并行
    两个任务真正同时在不同 CPU 核心上执行。例如,一个核心处理A程序,另一个核心处理B程序。

  • 并发
    单个核心在多个任务之间快速切换,让我们感觉它们像是“同时”进行。操作系统根据 PCB 中的状态、优先级等信息,不断切换调度进程。

并发编程的目的是提高程序的效率,特别是在处理多个任务时。它不要求任务必须在物理上完全同时进行,而是关注如何在合理的时间内调度多个任务,让它们看起来像是在并行执行。

线程

按照笔者学习的知识介绍:

一个线程就是一个 " 执行流 ". 每个线程之间都可以按照顺讯执行自己的代码 . 多个线程之间 " 同时 " 执行着多份代码, 在一个进程中,至少有一个线程.
我们可以将线程看作是进程内部真正 执行任务的实体
一个进程可以拥有一个或多个线程,这些线程之间可以同时、独立地运行各自的任务,而且它们共享同一个进程的资源。

为什么选择多线程编程

但是我们为什么需要多线程编程而不是多进程编程呢?
首先就是,"并发编程"成为了刚需,能更好的利用多核心cpu的资源
但是比起多进程编程,多线程编程更加轻量.
因为不管是创建一个进程,调度一个进程,销毁一个进程,都需要消耗更多的时间,光是去给这些进程分配内存空间,就已经是一个大活了
而线程依附于进程,但是每一个线程都可以独立的去工作,每一个线程也有 "上下文","记账信息","状态"等属性,当一个进程有多个线程时,它就有多个pcb,每个线程有一个pcb.
上述材料我们可以得出两个结论
一:每个线程可以独立的去cpu上调度执行
二:同一个进程的线程们共用一套内存空间和文件资源
每一个进程好比一个厂房,每一个线程就好比厂房里的生产线!  如果多个生产线放置在同一个厂房里,肯定比多租几个厂房放数量更少的生产线来得更节省资源.
所以,这就是多线程编程的好处

总结一下上述文字,就能得出大概两个结论:

  1. 提升 CPU 利用率

    • 多线程可以更好地利用多核 CPU。

    • 在单核 CPU 上,也可以通过快速切换,提升程序响应速度(并发)。

而由此引申出第二点

 资源开销小

  • 创建/销毁一个进程非常消耗资源(如内存空间的分配和管理)。

  • 而线程是依附于进程存在的,线程之间共享进程的资源(如内存、文件描述符),创建和切换开销远小于进程

 

2.在IDEA中如何简单创建一个线程 

线程是操作系统中的概念 . 操作系统内核实现了线程这样的机制 , 并且对用户层提供了一些 API 供用户使 用( 例如 Linux pthread ).
Java 标准库中 Thread 类可以视为是对操作系统提供的 API 进行了进一步的抽象和封装 .
在 Java 中,创建线程的方式有很多种,常见的有以下几种:

1. 通过继承Thread类

class MyThread extends Thread {
    @Override
    public void run() {
        while (true) {
            System.out.println("Thread is running");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

public class Demo {
    public static void main(String[] args) {
        MyThread thread = new MyThread();
        thread.start();  // 启动线程
    }
}

2. 通过实现 Runnable 接口

class MyRunnable implements Runnable {
    @Override
    public void run() {
        while (true) {
            System.out.println("Thread is running");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

public class Demo {
    public static void main(String[] args) {
        MyRunnable myRunnable = new MyRunnable();
        Thread thread = new Thread(myRunnable);
        thread.start();  // 启动线程
    }
}

3. 使用 Lambda 表达式

    Thread y = new Thread(() -> {
            while (true)
            {
                System.out.println("one Thread");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e)
                {
                    e.printStackTrace();
                    throw new RuntimeException(e);
                }
            }
        },"线程一"); // lambda 表达式写法
//        y.setDaemon(true); // 设置为后台线程
        y.start(); // 启动线程

3.如何简单使用jconsloe去查看创建好的线程

JConsole 是一个 Java 监控工具,用于监控 Java 应用程序的运行时性能,它能够提供线程、内存、垃圾回收等信息。通过 JConsole,我们可以查看程序的线程状态、CPU 使用情况等,有助于调试和优化程序。

我们可以在JDK中找到它,如图

示例代码 

public class demo2
{
    public static void main(String[] args) throws InterruptedException {
//        Thread t = new MyThread();
//        t.start();
        Runnable runnable = new MyRun();
        Thread t = new Thread(runnable);
//        t.start();
        Thread y = new Thread(() -> {
            while (true) {
                System.out.println("one Thread");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    throw new RuntimeException(e);
                }
            }
        }, "线程一"); // lambda 表达式写法
//        y.setDaemon(true); // 设置为后台线程
        y.start(); // 启动线程
        while (true) {
            System.out.println("soyo");
            Thread.sleep(1000);
        }
    }

}

打开jconsloe 

即可查看

结尾 

结尾部分,笔者再给大家汇总一下线程的优点,以及进程和线程的区别

线程的优点

1. 创建一个新线程的代价要比创建一个新进程小得多
2. 与进程之间的切换相比,线程之间的切换需要操作系统做的工作要少很多
3. 线程占用的资源要比进程少很多
4. 能充分利用多处理器的可并行数量
5. 在等待慢速I/O操作结束的同时,程序可执行其他的计算任务
6. 计算密集型应用,为了能在多处理器系统上运行,将计算分解到多个线程中实现
7. I/O密集型应用,为了提高性能,将I/O操作重叠。线程可以同时等待不同的I/O操作。

 进程和线程的区别

1. 进程是系统进行资源分配和调度的一个独立单位,线程是程序执行的最小单位。
2. 进程有自己的内存地址空间,线程只独享指令流执行的必要资源,如寄存器和栈。
3. 由于同一进程的各线程间共享内存和文件资源,可以不通过内核进行直接通信。
4. 线程的创建、切换及终止效率更高。

博客的内容就到这,这不是随便水的,好歹结合了笔者自己的思考,希望有人能看到这里吧,我会很感谢的!

评论 32
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值