协程和线程性能测试

这里测试使用的是协程的quasar框架。

代码使用CountDownLatch对线程进行控制,分别检测其创建和运行时间。

时间测试:

设想以下的场景,使用15个线程来调用某加了同步锁的方法,每次这个方法的执行时间在25ms左右,那线程和协程都需要多少时间完成方法调用:

线程:

         创建时间:2-3ms

         运行时间:375ms

协程:

         创建时间:150ms

         运行时间:375ms

可以发现协程的创建要比线程的创建花费更多的时间。

 

cpu占用测试:

另外从cup的占用角度来分析两者的区别,因为375ms太短,所以将线程数改为150来测试:

 

上图的左侧是协程运行的情况,右侧是线程运行的情况,总的来说,协程运行的cup占用峰值要比线程小,但持续时间比线程长。所以其实对一些长时间执行的任务,协程的运行开销应该比线程小一些。

 

去掉同步锁的情况:

另外协程对线程的优势应该上下文切换频繁的场景,所以不用锁的情况可能协程的运行效率更高,将同步锁去掉继续测试:

发现在线程数在150以上的情况下,协程的运行时间要比线程短,且随着线程数的增长,这种差距会增大。

 

总结:

所以总的来说,平时的场景时不太需要协程的,只有在线程常驻内存来处理长任务时,或是在需要大量线程来并发的时候,协程的效率会比线程高。对于一些短的任务,并发较少的情况,线程反而更具优势。

 

测试代码:

线程:

/**
 * @Auther: muyu
 * @Date: 2018-10-09-16:33
 */
import java.util.concurrent.CountDownLatch;

    class service{
         public void sleeps(CountDownLatch endGate, CountDownLatch startGate){
            try {
                startGate.await();
                Thread.sleep(25);
                System.out.println(Thread.currentThread().getName());
                endGate.countDown();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    class threadDemo implements Runnable{
        service ser = new service();
        CountDownLatch startGate;
        CountDownLatch endGate;
        public threadDemo(service ser,CountDownLatch endGate,CountDownLatch startGate){
            this.ser = ser;
            this.startGate = startGate;
            this.endGate = endGate;
        }
        public void run() {
            ser.sleeps(endGate,startGate);
        }
    }

    public class test4 {
        public static void main(String[] args){
            service ser = new service();
            threadDemo[] t = new threadDemo[150];
            CountDownLatch startGate = new CountDownLatch(1);
            CountDownLatch endGate = new CountDownLatch(150);

            for(int i=0;i<t.length;i++){
                t[i] = new threadDemo(ser,endGate,startGate);
                Thread t1 = new Thread(t[i]);
                t1.start();
            }
            long startTime = System.currentTimeMillis();
            startGate.countDown();
            try {
                endGate.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            long endTime = System.currentTimeMillis();
            System.out.println("用时: " + (endTime - startTime) + "ms");
        }
    }

协程:

import co.paralleluniverse.fibers.Fiber;
import co.paralleluniverse.fibers.SuspendExecution;
import co.paralleluniverse.strands.Strand;
import co.paralleluniverse.strands.SuspendableRunnable;
import java.util.concurrent.CountDownLatch;

/**
 * @Auther: muyu
 * @Date: 2018-10-11-16:52
 */

class service2 {
    public void doSleep(CountDownLatch startGate, CountDownLatch endGate) throws SuspendExecution {
        try {
            startGate.await();
            Strand.sleep(25);
            System.out.println(Thread.currentThread().getName());
            endGate.countDown();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
class threadDemo2 implements SuspendableRunnable {
    service2 ser2 = new service2();
    CountDownLatch startGate;
    CountDownLatch endGate;
    public threadDemo2(service2 ser2,CountDownLatch startGate,CountDownLatch endGate){
        this.ser2 = ser2;
        this.startGate = startGate;
        this.endGate = endGate;
    }
    @Override
    public void run() throws SuspendExecution, InterruptedException {
        ser2.doSleep(startGate,endGate);
    }
}

public class xieChengTest {

    public static void main(String[] args) throws InterruptedException, SuspendExecution {
        service2 ser = new service2();
        threadDemo2[] fiber = new threadDemo2[150];
        CountDownLatch startGate = new CountDownLatch(1);
        CountDownLatch endGate = new CountDownLatch(150);
        for(int i=0;i<fiber.length;i++){
            fiber[i] = new threadDemo2(ser,startGate,endGate);
            Fiber f = new Fiber(fiber[i]);
            f.start();
        }
        long startTime = System.currentTimeMillis();
        startGate.countDown();
        try {
            endGate.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        long endTime = System.currentTimeMillis();
        System.out.println("用时: " + (endTime - startTime) + "ms");
    }
}

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java线程和Kotlin协程是在JVM上实现并发的两种不同方式。Java线程是JVM中的虚拟线程,而Kotlin协程是作为库函数实现的。区别主要体现在以下几个方面: 1. 语法:Java线程使用与Java中常规线程相同的语法,易于使用并与现有代码集成。而Kotlin协程使用与Kotlin中的常规线程不同的语法,需要一些学习和适应。但是,协程提供了一些优势和简化,例如结构化并发、取消或错误处理。 2. 性能:虚拟线程协程通常都比常规线程更高效,并且可以更有效地利用资源。然而,实际的性能优势将取决于具体的用例和实施。一些基准测试表明,类似于虚拟线程的Go Goroutines比Kotlin协程具有更好的性能,但其他基准测试表明Kotlin协程性能优于Java虚拟线程。因此,总体上很难说哪一个更快或更好。 3. 成熟度:虚拟线程仍然是Project Loom的一个实验性功能,尚未成为官方Java版本的一部分。因此,它们不稳定或不受工具或库的广泛支持。相比之下,自2018年发布1.3版本以来,协程是Kotlin的一个稳定功能,更可靠,并且得到工具或库的良好支持。 综上所述,Java线程和Kotlin协程在语法、性能和成熟度方面存在一些区别。选择使用哪种方式取决于具体的需求和优先考虑的因素。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [Java 虚拟线程与 Kotlin 协程](https://blog.csdn.net/qq_52010446/article/details/131465664)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值