橘子学java之java中的协程

6 篇文章 0 订阅

一、关于协程

最近jdk19上了,java开始支持虚拟线程了,也就是所谓的协程,java的协程库是官方是这个https://openjdk.org/projects/loom/.我指的是oracle的java,阿里那个well的早就支持了,。只是官方的还不支持。
我倒是还没看那个,但是突然想起以前研究的一个东西,是一个大神自己写的协程库,也就是quasar,github的地址是这个:https://github.com/puniverse/quasar
在这里插入图片描述
下面先说一下我对协程的浅薄的理解,未必正确,不断学习。
以前我们常说的两个概念是进程和线程,也都知道进程是操作系统分配资源的单位,线程是运行程序的基本单位,一个进程里面可能有多个线程,同一个进程内部的线程共享进程资源,只是自己独自占据一些必要的运行时数据资源,然后我们还知道进程切换因为涉及资源的分配是很耗时的,线程切换比进程好一些,但是也涉及上下文的切换也是很耗的,因为他们都是属于操作系统的资源,程序运行在用户态,切换需要在内核态进行切换,所以需要程序进入内核态,这是一个很大的开销。
但是协程不是,协程是属于线程的,一个线程内部有多个协程,协程和操作系统没必然从属关系,他是多个函数,是属于用户态的,所以他的操作切换之类的不需要陷入内核,这就减少了很多开销。
他的切换只是在线程内部的切换,因为都是在用户态,所以多个协程函数只能在一个线程内部串行,因为不是属于内核的,所以不能并行调度,一个线程内部只能串行,当一个协程执行的时候,其余协程是挂起的。
OK,至此为止我们大概有个理解了。

二、quasar

quasar是一个大神写的三方的协程库,我们来看看。据说这个大神已经入职oracle了,并且正是java的虚拟线程的开发者。
https://github.com/puniverse/quasar
他是操作了字节码那块了,原理底层我们不去研究,这里先看看用法对比一下有啥优点。
我们设计一个需求:

一万和线程或者协程,运行200万次运算,看看耗时。

1、引入jar包

 <!--协程依赖-->
 <dependency>
     <groupId>co.paralleluniverse</groupId>
     <artifactId>quasar-core</artifactId>
     <version>0.7.10</version>
     <classifier>jdk8</classifier>
 </dependency>

2、一万个线程

/**
 * @Author levi
 * @Description //TODO 
 * @Date 21:50 2022-10-9
 * @Param  * @param null
 * @return 
 **/
public class JavaThread {
    // 100万个线程进行调度切换成本巨几把高
    static  int THREAD_LENTH = 10000;//time cost:129242

    public static void main(String[] args) {
        long startTime = System.currentTimeMillis();
        Thread[] threads = new Thread[THREAD_LENTH];
        // 给数组里面初始化线程,以及放进去任务
        for (int i = 0; i < threads.length; i++) {
            threads[i] = new Thread(()->{
                calc();
            });
        }

        // 在这里启动线程进行调度
        for (int i = 0; i < threads.length; i++) {
            threads[i] .start();
        }

        // 主线程在这里等等结果,等其他线程结束了一起结束
        for (int i = 0; i < threads.length; i++) {
            try {
                threads[i].join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("100万个线程运算200万次时间花销为:" + (System.currentTimeMillis() - startTime));
    }

    // 一个运算的累加函数
    public static void calc() {
        int result = 0;
        // 运算200万次,每次都加一下
        for (int i = 0; i < 200; i++) {
            for (int j = 0; j < 10000; j++) {
                result += i;
            }
        }
    }
}
1万个线程运算200万次时间花销为:8408

3、一万个协程

import co.paralleluniverse.fibers.Fiber;

/**
 * @Author levi
 * @Description //TODO 
 * @Date 21:51 2022-10-9
 * @Param  * @param null
 * @return 
 **/
public class JavaFiber {
    // 十万个协程,操作系统会合适的分布在几个线程中,我测试的三个,三个线程调度就轻多了
    static  int FIBER_LENTH = 10000;//time cost:1099

    public static void main(String[] args) {
        long startTime = System.currentTimeMillis();
        // 创建十万个协程的一个数组
        Fiber<Void>[] fibers = new Fiber[FIBER_LENTH];
        // 给数组里面初始化协程,以及放进去任务
        for (int i = 0; i < fibers.length; i++) {
            fibers[i] = new Fiber(()->{
                calc();
            });
        }


        // 在这里启动线程进行调度
        for (int i = 0; i < fibers.length; i++) {
            fibers[i] .start();
        }

        // 主线程在这里等等结果,等其他协程结束了一起结束
        for (int i = 0; i < fibers.length; i++) {
            try {
                fibers[i].join();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        System.out.println("100万个协程运算200万次时间花销为:" + (System.currentTimeMillis() - startTime));
    }

    // 一个运算的累加函数
    public static void calc() {
        int result = 0;
        // 运算200万次,每次都加一下
        for (int i = 0; i < 200; i++) {
            for (int j = 0; j < 10000; j++) {
                result += i;
            }
        }
    }
}
1万个协程运算200万次时间花销为:627

我们看到协程的耗时比线程少了机会十多倍,这就是因为协程的切换是就在用户态,基本不会到内核态里面,都是在一个线程里面串行执行的方法,不涉及内核态用户态的切换。所以他的开销是很小的,这种优势在你线程协程个数越大的时候越明显,OK,后面我们学习一下IO模型,然后开始一点点的看看JDK虚拟线程的设计。

  • 6
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值