纤程与Quasar
Java使用的是系统级线程,也就是说,每次调用new Thread(....).run(),都会在系统层面建立一个新的线程,然鹅新建线程的开销是很大的(每个线程默认情况下会占用1MB的内存空间,当然你愿意的话可以用-Xss来调小点),更不要说线程切换带来的开销了
为了节省开销,程序员玩出了很多花样。
最常用的是线程池(线程复用,但是完全无法处理阻塞调用的问题)
以及事件驱动框架(NIO或者Netty,用少量的工作线程来服务大量的慢速IO连接,但是EventLoop中也不能有阻塞调用,耗时的逻辑必须放在额外的线程池里处理)
但是NIO的代码难写也难懂,像我这种懒惰的程序猴子,最喜欢的还是一个线程对应一个连接这种简单粗暴的编程手法。
纤程(Coroutine)是我们的救星
所谓的纤程,或者协程,可以理解为是一种轻量级的线程,它与线程的主要区别在于
a. 线程切换的过程是由系统内核完成,切换的过程中会进入到内核态。而纤程则完全工作在用户态。
b. 线程是否发生切换是由操作系统决定的(抢占式调度),工作线程本身没有决定权。而纤程的切换是需要工作纤程主动放弃CPU,这样调度器才能让另外一个纤程继续运行。
很多语言已经内置了纤程,最著名的应该就是Go了,用go关键字,就能直接创建一个纤程并在其中为所欲为,其他的Scheduler会自动帮你搞定。所以Go能相对容易的写出正确的高并发程序。
可惜的是,Java没有官方的纤程支持,好在有个叫做Quasar的库可堪一用
使用这个lib,你就能在Java程序中创建纤程了,代码大概长这个样子:
public static void main(String[] args)
throws ExecutionException, InterruptedException, SuspendExecution {
int FiberNumber = 1_000_000;
CountDownLatch latch = new CountDownLatch(1);
AtomicInteger counter = new AtomicInteger(0); for (int i = 0; i < FiberNumber; i++) {
new Fiber(() -> {
counter.incrementAndGet();
if (counter.get() == FiberNumber) {
System.out.println("done");
}
Strand.sleep(1000000);
}).start();
}
latch.await();
}
在上面这段代码中,我们直接创建了一百万个纤程,如果是一般的Thread,不考虑OS能否负担得起,单单占用的内存就要1T起步。
但是这段程序实际占用的内存只在1G出头,也就是说每个纤程的内存占用只在1K左右。
这是如何做到的?
Quasar在编译时会对代码进行扫描,如果方法带有Suspendable注解,或者抛出SuspendExecution,或者在配置文件中被指定,Quasar会直接修改生成的字节码,在park方法的前后,插入一些字节码。
这些字节码会记录此时纤程的执行状态(相关的局部变量与操作数栈),然后通过抛出异常的方式将CPU的控制权从当前协程交回到控制器
此时控制器可以再次调度另外一个纤程运行,并通过之前插入的那些字节码恢复当前纤程的执行状态,使程序能继续正常执行。
并且,这些操作是非常轻量的,所以内存消耗极小,也不会对CPU带来太多的额外开销(据说在3%-5%)
参考资料
Coroutine in Java - Quasar Fiber实现
纤程与Quasar的更多相关文章
- Java 中的纤程库 – Quasar
来源:鸟窝, colobu.com/2016/07/14/Java-Fiber-Quasar/ 如有好文章投稿,请点击 → 这里了解详情 最近遇到的一个问题大概是微服务架构中经常会遇到的一个问题: 服 ...
- 继续了解Java的纤程库 – Quasar
前一篇文章Java中的纤程库 – Quasar中我做了简单的介绍,现在进一步介绍这个纤程库. Quasar还没有得到广泛的应用,搜寻整个github也就pinterest/quasar-thrift这 ...
- JAVA协程 纤程 与Quasar 框架
ava使用的是系统级线程,也就是说,每次调用new Thread(....).run(),都会在系统层面建立一个新的线程,然鹅新建线程的开销是很大的(每个线程默认情况下会占用1MB的内存空间,当然你愿 ...
- 协程,纤程(Fiber),或者绿色线程(GreenThread)
纤程(Fiber),或者绿色线程(GreenThread) 面试官:你知道协程吗? 你:订机票的那个吗,我常用. 面试官:行,你先回去吧,到时候电话联系 ........ 很尴尬,但是事实是,很大一部 ...
- 第12章 纤程(Fiber)
12.1 纤程对象的介绍 (1)纤程与线程的比较 比较 线程(Thread) 纤程(Fiber) 实现方式 是个内核对象 在用户模式中实现的一种轻量级的线程,是比线程更小的调度单位. 调度方式 由Mi ...
- windows 纤程
纤程本质上也是线程,是多任务系统的一部分,纤程为一个线程准并行方式调用多个不同函数提供了一种可能,它本身可以作为一种轻量级的线程使用.它与线程在本质上没有区别,它也有上下文环境,纤程的上下文环境也是一 ...
- Windows核心编程:第12章 纤程
Github https://github.com/gongluck/Windows-Core-Program.git //第12章 纤程.cpp: 定义应用程序的入口点. // #include & ...
- 基于纤程(Fiber)实现C++异步编程库(一):原理及示例
纤程(Fiber)和协程(coroutine)是差不多的概念,也叫做用户级线程或者轻线程之类的.Windows系统提供了一组API用户创建和使用纤程,本文中的库就是基于这组API实现的,所以无法跨平台 ...
- DELPHI纤程的演示
DELPHI纤程的演示 DELPHI7编译运行通过. 纤程实现单元: unit FiberFun; //Fiber(纤程测试Demo)//2018/04/11//QQ: 287413288 //参考 ...
随机推荐
- PHP判断类型的方法
1.gettype():获取变量类型 2.is_array():判断变量类型是否为数组类型 3.is_double():判断变量类型是否为倍浮点类型 4.is_float():判断变量类型是否为浮点类 ...
- P1717 钓鱼
题目描述 话说发源于小朋友精心设计的游戏被电脑组的童鞋们藐杀之后非常不爽,为了表示安慰和鼓励,VIP999决定请他吃一次“年年大丰收”,为了表示诚意,他还决定亲自去钓鱼,但是,因为还要准备2013NO ...
- TCP/IP Note1
TCP/IP(Transmission Control Protocol / Internet Protocol)是用于Internet的通信协议. 计算机通信协议:是指对那些计算机必须遵守以便彼此通 ...
- BZOJ1934 [Shoi2007]Vote 善意的投票 【最小割】
题目 幼儿园里有n个小朋友打算通过投票来决定睡不睡午觉.对他们来说,这个问题并不是很重要,于是他们决定发扬谦让精神.虽然每个人都有自己的主见,但是为了照顾一下自己朋友的想法,他们也可以投和自己本来意愿 ...
- hadoop基础----hadoop实战(七)-----hadoop管理工具---使用Cloudera Manager安装Hadoop---Cloudera Manager和CDH5.8离线安装
hadoop基础----hadoop实战(六)-----hadoop管理工具---Cloudera Manager---CDH介绍 简介 我们在上篇文章中已经了解了CDH,为了后续的学习,我们本章就来 ...
- Codeforces Round #350 (Div. 2) D1
D1. Magic Powder - 1 time limit per test 1 second memory limit per test 256 megabytes input standard ...
- codeforces 1077F1
题目:https://codeforces.com/contest/1077/problem/F1 题意: 你有n幅画,第i幅画的好看程度为ai,再给你两个数字k,x 表示你要从中选出刚好x幅画,并且 ...
- 第九届蓝桥杯C/C++B组题解附代码
1.标题:第几天 2000年的1月1日,是那一年的第1天.那么,2000年的5月4日,是那一年的第几天? 125天 打开日历就ok 2. 标题:明码 汉字的字形存在于字库中,即便在今天,16点阵的字库 ...
- 自定义orderBy字母函数
orderedUsers: function () { var arr = this.users; for (var i = 0; i < arr.length - 1; i++) { for ...
- 带依赖包的maven打包配置
转载自:http://outofmemory.cn/code-snippet/2594/carry-yilai-bao-maven-dabao-configuration 可以在maven的packa ...