其他链接: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导入到本地仓库
<!-- https://mvnrepository.com/artifact/co.paralleluniverse/quasar-core -->
<dependency>
<groupId>co.paralleluniverse</groupId>
<artifactId>quasar-core</artifactId>
<version>0.7.6</version>
</dependency>
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<Void>[] fibers = new Fiber[size];
for (int i = 0; i < fibers.length; i++) {
fibers[i] = new Fiber<Void>(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点进修”,我们会有更多、且及时的资料推送给您,欢迎多多交流!