其他链接:JAVA相关的深度技术博客链接
相信很多小伙伴们在面试的时候,面试官都会提这样的一个问题。
请你说说什么是进程,什么是线程,两者有什么区别?
很多小伙伴可能会直接说,进程就是一个个后台程序,线程是在进程中创建出来的。这种回答也没什么毛病,粗略的来说是对的,就是相对不够专业。
首先,我们得了解计算机底层层面是逻辑图,然后再深刻理解:进程、线程、纤程
按上面计算机底层逻辑,我们可以这样回答,就非常专业了,也是面试官想要的答案:
- 进程:是操作系统资源分配的基本单位,比如内存、打开文件、网络IO,分配了独立的内存空间
- 线程:是操作系统资源调度的基本单位,cpu分配的基本单位
- 纤程:是用户态的线程,是线程中的线程,切换和调度不需要经过OS(操作系统)。;轻量级的线程 - 线程
纤程的优势:
- 占有的资源少,为什么说他占有资源少呢?举例:操作系统要启一个线程前后要为这个线程配的内存数据大概有1M,而纤程大概是4K
- 由于纤程非常的轻量级,所以切换比较简单
- 可以同时被启动很多个(10万个都没问题)
目前支持内置纤程的语言Kotlin Scala Go 等,可惜的是,Java没有官方的纤程支持,好在有个叫做Quasar的库可堪一用
下面我就举个例子来证明一下,进程、线程、以及 纤程先对于线程来说的优势,有兴趣的小伙伴可以试试
什么是进程?
- // 进程:是操作系统资源分配的基本单位,比如内存、打开文件、网络IO,分配了独立的内存空间
- public class T00_Process {
- public static void main(String[] args) {
- System.out.println("hello world");
- }
- }
什么是线程,及与纤程计算对比
- // 线程:是操作系统资源调度的基本单位,cpu分配的基本单位
- public class T01_HelloFiber {
- public static void main(String[] args) throws InterruptedException {
- long start = System.currentTimeMillis();
- Runnable r = new Runnable() {
-
- @Override
- public void run() {
- calc();
- }
- };
-
- int size = 10000;
- Thread[] threads = new Thread[size];
- for (int i = 0; i < threads.length; i++) {
- threads[i] = new Thread(r);
- }
-
- for (int i = 0; i < threads.length; i++) {
- threads[i].start();
- }
-
- for (int i = 0; i < threads.length; i++) {
- threads[i].join();
- }
-
- long end = System.currentTimeMillis();
- System.out.println(end - start);
-
- }
-
- private static void calc() {
- int result = 0;
- for (int m = 0; m < 10000; m++) {
- for (int i = 0; i < 200; i++) {
- result += i;
- }
- }
- }
- }
什么是纤程,及与线程计算对比
首先像前面说的那样,java 原生没有提供纤程支持,需要依赖于 Quasar的库,所以需要将依赖包,通过pom.xml导入到本地仓库
-
co.paralleluniverse -
quasar-core -
0.7.6
-
- import co.paralleluniverse.fibers.Fiber;
- import co.paralleluniverse.fibers.SuspendExecution;
- import co.paralleluniverse.strands.SuspendableRunnable;
-
- import java.util.concurrent.ExecutionException;
-
-
- // 纤程:是用户态的线程,是线程中的线程,切换和调度不需要经过OS(操作系统)。;轻量级的线程 - 线程
- public class T02_HelloFiberV2 {
- public static void main(String[] args) throws InterruptedException, ExecutionException {
- long start = System.currentTimeMillis();
- int size = 10000;
- Fiber
[] fibers = new Fiber[size]; - for (int i = 0; i < fibers.length; i++) {
- fibers[i] = new Fiber
(new SuspendableRunnable() { -
- @Override
- public void run() throws SuspendExecution, InterruptedException {
- calc();
- }
- });
- }
-
- for (int i = 0; i < fibers.length; i++) {
- fibers[i].start();
- }
-
- for (int i = 0; i < fibers.length; i++) {
- fibers[i].join();
- }
-
- long end = System.currentTimeMillis();
- System.out.println(end - start);
-
- }
-
- private static void calc() {
- int result = 0;
- for (int m = 0; m < 10000; m++) {
- for (int i = 0; i < 200; i++) {
- result += i;
- }
- }
- }
- }
多线程与多纤程计算耗时对比结果如下:
有兴趣的小伙伴可以把代码copy下去自己试一试,当启动的线程数量和纤程数量越大的时候,体现纤程优势的效果越明显。
最后说一下纤程的应用场景:纤程 vs 线程池:很短的计算任务,不需要和内核打交道,并发量高!
文章最后,给大家推荐一些受欢迎的技术博客链接:
- Hadoop相关技术博客链接
- Spark 核心技术链接
- JAVA相关的深度技术博客链接
- 超全干货--Flink思维导图,花了3周左右编写、校对
- 深入JAVA 的JVM核心原理解决线上各种故障【附案例】
- 请谈谈你对volatile的理解?--最近小李子与面试官的一场“硬核较量”
- 聊聊RPC通信,经常被问到的一道面试题。源码+笔记,包懂
欢迎扫描下方的二维码或 搜索 公众号“10点进修”,我们会有更多、且及时的资料推送给您,欢迎多多交流!
评论记录:
回复评论: