[JavaEE] 线程与进程的区别详解
创始人
2024-05-01 01:12:00
0


 专栏简介: JavaEE从入门到进阶

题目来源: leetcode,牛客,剑指offer.

创作目标: 记录学习JavaEE学习历程

希望在提升自己的同时,帮助他人,,与大家一起共同进步,互相成长.

学历代表过去,能力代表现在,学习能力代表未来! 


目录

认识线程(Thread)

1. 线程是什么?

2. 为什么要有线程?

3. 线程和进程的区别?

4. Java线程和操作系统线程的关系 

5. 创建多线程

6. 使用JConsole 查看线程状态


认识线程(Thread)

1. 线程是什么?

一个线程就是一个执行流 , 每个线程都可以按照自己的顺序来执行代码 , 多个线程同时执行着多份代码.

例如: 一家公司的会计张三去银行办理业务 , 业务范畴很广 , 有财务转账 , 社保缴纳 , 员工福利发放. 如果只有张三一个会计 , 就会耗费很长的时间. 为了节省时间 , 公司张三又叫来了李四和王五 , 三个人分别排队叫号 , 自此就有三个执行流共同完成任务 , 但本质上他们还是办理同一家公司的业务 . 此时我们就把这种情况称为多线程 , 将一个大任务分成多个小任务 , 交给不同执行流分别排队执行.其中李四和王五是张三叫来的 , 那么张三就是主线程.(Main Thread).


2. 为什么要有线程?

首先 , "并发编程" 成为 "刚需".

  • 单核CPU的发展遇到了瓶颈 , 想要提高算力 , 需要使用多核CPU. 而并发编程恰好能更充分的利用多核CPU资源.
  • 有些任务常见需要等待"IO" , 为了让程序在等待"IO"的同时做一些其他工作 , 也需要用到并发编程.

其次 , 虽然多进程能实现并发编程 , 但线程比进程更轻量.

  • 创建线程比进程更快
  • 调度线程比进程更快
  • 销毁线程比进程更快

 Tips:虽然线程比进程更轻量 , 但人们并不满足于此 , 于是有了"线程池"(Thread Pool)和协程(Coroutine)


3. 线程和进程的区别?

维度多进程多线程总结
数据共享 , 同步

数据是分开的 , 共享复杂;

同步简单.

多线程共享进程数据 , 共享简单;

同步复杂

各有优势
内存, CPU

占用内存多 , CPU利用率低

占用内存少 , CPU利用率高

线程占优
创建销毁, 切换创建销毁 , 切换复杂 , 速度慢创建销毁 , 切换简单 , 速度快线程占优
编程调试编程简单 , 调试简单编程复杂 , 调试复杂进程占优
可靠性进程间不会相互影响

一个线程挂掉将导致

整个进程挂掉

进程占优
分布式

适用于多核 , 多机分布;

如果一台机器不够 , 

扩展到多台机器比较简单

适用于多核分布线程占优
  • 进程包含线程 , 每个进程中至少有一个线程存在 , 即主线程.
  • 进程和进程之间不共享内存空间 , 同一个进程的多个线程之间共用进程的同一份资源.(内存和文件描述符表)
  • 进程是系统分配资源的最小单位 , 线程是系统调度的最小单位.

还是之前的例子 , 每个来银行办理业务的客户相当于一个进程 , 他们的票据肯定不同 , 否则银行卡中的钱就被别人取走了 , 而张三李四王五虽然是三个不同的执行流 , 但办理的都是同一家公司的业务 , 所以票据是共享的 , 这就是多线程和多进程最大的区别.


4. Java线程和操作系统线程的关系 

线程是操作系统中的概念 , 操作系统内核实现了线程这样的机制 , 并且提供了一系列的API供用户层使用 , 例如Linux系统的pthread库.

Java标准库中的Thread类可以看做是对操作系统提供的线程API做进一步的抽象和封装.


5. 创建多线程

1) 继承Thread重写run()

t.start 真正创建了一个线程 , 线程是独立的执行流. run() 只是描述了线程要执行的任务是什么 , 

class MyThread extends Thread{@Overridepublic void run(){System.out.println("Hello thread");}
}
public static void main(String[] args) {Thread t = new MyThread();t.start();//start 创建了一个新的线程 , 新的线程负责执行t.run().System.out.println("Hello main");}

2) 实现Runnable()

将任务与线程区分开来,让线程和任务之间解耦合.(低耦合) 好处是如果后期要改成多进程 , 或者线程池 , 或者协程.....此时代码改动比较小.

 class MyRunnable implements Runnable {//Runnable 作用 , 描述一个"要执行的任务" , run 方法就是任务执行的细节.@Overridepublic void run() {System.out.println("Hello Thread");}
}
public static void main(String[] args) {//描述一个任务Runnable runnable = new MyRunnable();//把任务交给线程来执行Thread t = new Thread(runnable);t.start();}

3) 使用匿名内部类

new Thread 创建了 Thread 类的子类 , 因为子类没有名字叫匿名匿名内部类 , 并且让 t 引用指向该实例.

public static void main(String[] args) {Thread t = new Thread(){@Overridepublic void run(){System.out.println("Hello thread");}};t.start();}

4) 使用匿名内部类实现Runnable()

该方法与第二种方法本质相同. 只不过把实现 Runnable 的任务交给匿名内部类.最后将匿名内部类的实例交给 Thread 类的构造方法.

public static void main4(String[] args) {Thread t = new Thread(new Runnable() {@Overridepublic void run() {System.out.println("Hello thread");}});t.start();}

5)j简便写法 Lambda表达式

直接把 lambda 传给Thread 构造方法.

 public static void main5(String[] args) {Thread t = new Thread(()->{System.out.println("Hello world");});t.start();}

6. 使用JConsole 查看线程状态

JConsole 是 jdk 自带的一种基于JMX的可视化监控 , 管理工具.主要用于查看线程的状态.

打开 jdk 进入bin目录 , 找到 jconsole.

jconsole只能查看正在运行的线程状态 , 我们先在本地 ideal 运行一个多线程的Java程序.这时打开jconsole 找到我们创建的Java程序 , 点击连接.

 忽略不安全的连接提示 , 进入线程专栏.

 此时我们可以看到多个线程 , 其中main是主线程 , Thread-0是我们创建的另一个线程.其余线程都是JVM自带的.

 选择指定的线程后 , 在堆栈跟踪中就可以查看到线程调用栈具体的执行细节. 这对于后期多线程程序的调试工作有很大的用处.

相关内容

热门资讯

监控摄像头接入GB28181平... 流程简介将监控摄像头的视频在网站和APP中直播,要解决的几个问题是:1&...
Windows10添加群晖磁盘... 在使用群晖NAS时,我们需要通过本地映射的方式把NAS映射成本地的一块磁盘使用。 通过...
protocol buffer... 目录 目录 什么是protocol buffer 1.protobuf 1.1安装  1.2使用...
在Word、WPS中插入AxM... 引言 我最近需要写一些文章,在排版时发现AxMath插入的公式竟然会导致行间距异常&#...
【PdgCntEditor】解... 一、问题背景 大部分的图书对应的PDF,目录中的页码并非PDF中直接索引的页码...
Fluent中创建监测点 1 概述某些仿真问题,需要创建监测点,用于获取空间定点的数据࿰...
educoder数据结构与算法...                                                   ...
MySQL下载和安装(Wind... 前言:刚换了一台电脑,里面所有东西都需要重新配置,习惯了所...
修复 爱普生 EPSON L4... L4151 L4153 L4156 L4158 L4163 L4165 L4166 L4168 L4...
MFC文件操作  MFC提供了一个文件操作的基类CFile,这个类提供了一个没有缓存的二进制格式的磁盘...