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实现

次时代Java编程(一):Java里的协程

纤程与Quasar的更多相关文章

  1. Java 中的纤程库 – Quasar

    来源:鸟窝, colobu.com/2016/07/14/Java-Fiber-Quasar/ 如有好文章投稿,请点击 → 这里了解详情 最近遇到的一个问题大概是微服务架构中经常会遇到的一个问题: 服 ...

  2. 继续了解Java的纤程库 – Quasar

    前一篇文章Java中的纤程库 – Quasar中我做了简单的介绍,现在进一步介绍这个纤程库. Quasar还没有得到广泛的应用,搜寻整个github也就pinterest/quasar-thrift这 ...

  3. JAVA协程 纤程 与Quasar 框架

    ava使用的是系统级线程,也就是说,每次调用new Thread(....).run(),都会在系统层面建立一个新的线程,然鹅新建线程的开销是很大的(每个线程默认情况下会占用1MB的内存空间,当然你愿 ...

  4. 协程,纤程(Fiber),或者绿色线程(GreenThread)

    纤程(Fiber),或者绿色线程(GreenThread) 面试官:你知道协程吗? 你:订机票的那个吗,我常用. 面试官:行,你先回去吧,到时候电话联系 ........ 很尴尬,但是事实是,很大一部 ...

  5. 第12章 纤程(Fiber)

    12.1 纤程对象的介绍 (1)纤程与线程的比较 比较 线程(Thread) 纤程(Fiber) 实现方式 是个内核对象 在用户模式中实现的一种轻量级的线程,是比线程更小的调度单位. 调度方式 由Mi ...

  6. windows 纤程

    纤程本质上也是线程,是多任务系统的一部分,纤程为一个线程准并行方式调用多个不同函数提供了一种可能,它本身可以作为一种轻量级的线程使用.它与线程在本质上没有区别,它也有上下文环境,纤程的上下文环境也是一 ...

  7. Windows核心编程:第12章 纤程

    Github https://github.com/gongluck/Windows-Core-Program.git //第12章 纤程.cpp: 定义应用程序的入口点. // #include & ...

  8. 基于纤程(Fiber)实现C++异步编程库(一):原理及示例

    纤程(Fiber)和协程(coroutine)是差不多的概念,也叫做用户级线程或者轻线程之类的.Windows系统提供了一组API用户创建和使用纤程,本文中的库就是基于这组API实现的,所以无法跨平台 ...

  9. DELPHI纤程的演示

    DELPHI纤程的演示 DELPHI7编译运行通过. 纤程实现单元: unit FiberFun; //Fiber(纤程测试Demo)//2018/04/11//QQ: 287413288 //参考 ...

随机推荐

  1. LeetCode难度和面试频率(转)

    转自:http://www.cnblogs.com/ywl925/p/3507945.html    ID Question   Diff  Freq  Data Structure  Algorit ...

  2. JAVA高并发处理------多线程

    线程安全概念:当多个线程访问某一个类(对象或方法)时,这个对象始终都能表现出正确的行为,那么这个类(对象或方法)就是线程安全的. 分析:当多个线程访问myThread的run方法时,以排队的方式进行处 ...

  3. window+kafka

    window环境搭建zookeeper,kafka集群 为了演示集群的效果,这里准备一台虚拟机(window 7),在虚拟机中搭建了单IP多节点的zookeeper集群(多IP节点的也是同理的),并且 ...

  4. 【bzoj3653】谈笑风生 DFS序+树状数组

    题目描述 给出一棵以1为根的有根树,q次询问,每次询问给出a和k,求点对 (b,c) 的数目,满足:a.b.c互不相同,b与a距离不超过k,且a和b都是c的祖先. 输入 输入文件的第一行含有两个正整数 ...

  5. 【心情】HNOI2018游记

    Day 0. 全机房的人好像都在做题.然而下午是社团节的游园会,身为社干的我风风雨雨在外面各种搬凳子搬椅子换场地招待外校同学……就这样我好像什么都没有复习. 晚上就一起去酒店了.大概因为是高一的缘故, ...

  6. chrome 不支持12px以下字体为题的解决

    现英文9px 设置 在chrome 下无效,可以通过 -webkit-transform: scale(0.75); 12*0.75 =9  得到小字体(在chrome浏览器下 大小缩放到0.75倍) ...

  7. java AWT repaint paint update 方法

    paint(Graphic g): awt调用这个方法有2种形式.程序驱动方式和系统驱动方式. 在系统驱动的情况下(比如界面第一次显示组件),系统会判断组件的显示区域,然后向事件分发线程发出调用pai ...

  8. jw player学习笔记三---发布到其它网站

    一.通过官网发布向导 登陆 http://www.longtailvideo.com,注册一个账号,进入你的用户管理中心,如下图 然后按提示,一步步操作,就会得到js代码了. 二.自己服务器发布 &l ...

  9. javascript错误处理(转)

    1.onerror事件处理函数onerror事件处理函数是第一个用来协助javascript处理错误的机制.页面上出现异常时,error事件便在window对象上触发.例如: <html> ...

  10. 【BZOJ1475】方格取数 [最小割]

    方格取数 Time Limit: 5 Sec  Memory Limit: 64 MB[Submit][Status][Discuss] Description 在一个n*n的方格里,每个格子里都有一 ...