Java线程 VS Golang协程

虚拟线程的定义及使用 长期以来,虚拟线程是 Java 中最重要的创新之一。 它们是在 Project Loom 中开发的,自 Java 19 作为预览功能以来一直包含在 JDK 中,自 Java 21 作为最终版本 (JEP 444) 以来,它们已包含在 JDK 中。 阅读详情

本文不从语言角度谈论好与不好。本文从性能测试角度分析一下Java线程与Golang协程的区别

用例设计

用 java 实现多线程任务处理:启动一定数量的等待线程或空转线程,并让启动的线程维持固定时间(60秒)
用golang实现多协程任务处理:启动一定数量的等待协程或空转协程,并让启动的协程维持固定时间(60秒)

测试结果

Java

在这里插入图片描述

Golang

在这里插入图片描述

结果分析

内存使用

Java线程的内存使用包括(约1Mb的虚拟内存 和 20Kb到60Kb的固定内存),空转状态的Java线程和sleep状态的Java线程在内存占用方面几乎无差别.
Golang协程的内存使用方面(不需要虚拟内存, 2Kb到4Kb的固定内存),空转状态的Golang协程和sleep状态的Golang协程在内存占用方面几乎无差别.

结论: Golang协程在内存开销方面比java线程有优势,开100w的Golang协程需占固定内存2.6G,虚拟内存2.6G。受限于内存大小没办法开100wjava线程

  • Java数据
条件虚拟内存消耗每个线程消耗虚拟内存固定内存消耗每个线程消耗固定内存
sleep线程(501-1)10592640Kb-10073528Kb500 * 1038.22Kb73420Kb-43312Kb500 * 60.216Kb
sleep线程(1001-501)11113744Kb-10592640Kb500 * 1042.20Kb84368Kb-73420Kb500 * 21.896Kb
sleep线程(1001-1)11113744Kb-10073528Kb1000 * 1040.21Kb84368Kb-43312Kb1000 * 41.056Kb
空转线程(101-1)10177000Kb-10073556Kb100 * 1034.44Kb46828Kb-43528Kb100 * 33.00Kb
空转线程(501-101)10592640Kb-10177000Kb400 * 1039.10Kb54484Kb-46828Kb400 * 19.14Kb
空转线程(501-1)10592640Kb-10073556Kb500 * 1038.16Kb54484Kb-43528Kb500 * 21.91Kb
  • Golang数据
条件虚拟内存消耗每个协程消耗虚拟内存固定内存消耗每个协程消耗固定内存问题
sleep协程(101-1)4976592Kb-4975812Kb100 * 7.80Kb2900Kb-2568Kb100 * 3.32Kb无
sleep协程(501-1)4976592Kb-4975812Kb500 * 1.56Kb4108Kb-2568Kb500 * 3.08Kb无
sleep协程(1001-501)4976592Kb-4976592Kb500 * 0Kb5452Kb-4108Kb500 * 2.69Kb无
sleep协程(100w-1)7636288Kb-4975812Kb100w * 2.6Kb2613152Kb-2568Kb100w * 2.61Kb无
空转协程(101-1)4975556Kb-4975556Kb100 * 0Kb2816Kb-2532Kb100 * 2.84Kb无
空转协程(501-1)4975556Kb-4975556Kb500 * 0Kb3836Kb-2532Kb500 * 2.60Kb无
空转协程(1001-501)4975812Kb-4975556Kb500 * 0.51Kb5208Kb-3836Kb500 * 2.74Kb无
空转协程(100w-1)无参考意义无参考意义无参考意义无参考意义实际没有达到100w协程同时运行
系统线程消耗

每个java线程对应1个系统线程,Golang使用的系统线程数很少且不随协程数量变化
结论: Golang协程在系统线程使用方面有优势,如果开启过多的系统线程cpu要用大量的时间做线程切换反而降低了效率

  • Java数据
    在这里插入图片描述
  • Golang数据
    在这里插入图片描述
并发极限,执行效率

因单个协程占用的内存资源更少,所以机器能支持更多的Golang协程创建,所以在并发极限方面Golong 有优势
因减少了系统线程的切换让cpu专注于执行工作,所以Golang在执行效率方面有优势

实际场景

使用java多线程开发时
1 因频繁的线程切换会让整体执行效率降低,应尽量避免创建太多的线程。
2 因长时间占用cpu会让剩余的任务堆积等待,应该尽量避免单个线程长时间占用cpu。
3 使用线程池(享元模式)是一种很好的执行多任务的手段。

golang携程
golang 在网络IO中更具备优势,不过golang协程在某些方面也有问题
例如 磁盘IO是没实现poll方法的,不能用 epoll 池。所以磁盘io没有等待事件, Golang的Goroutine 会卡线程。如果OS 内核线程抽象Machine全部卡住,Go runtime 创建更多的线程来保证一直有可运行的 Machine。这种情况下也会造出像java一样的大量系统线程

展望

  • java什么时候也能有协程
    OpenJDK 的 JEP 425 :虚拟线程(预览版)功能提案显示:Java 平台将引入虚拟线程特性(期待已久的协程)
    有关虚拟线程的更多信息可在 OpenJDK 的 JDK Issue-8277131 中查看,目前该提案于 2021/11/15 创立,目前还处于 JEP 流程的第一阶段,距离稳定版本还需要一段时间。

测试机器机器信息

  • 机器年代 :2014
  • 操作系统 : MacOS
  • 内存 :16G / 1600MHZ / DDR3
    *CPU :两核 / Intel Core i5 / 2.6 GHz / L2缓存256KB / L3缓存3MB

测试代码

Java
package org.example;

import com.google.common.base.Stopwatch;
import org.codehaus.plexus.util.StringUtils;
import org.junit.Test;

import java.io.IOException;
import java.io.PipedReader;
import java.io.PipedWriter;
import java.lang.management.ManagementFactory;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class ThreadTest {
    enum ThreadType {
        RUN_THREAD,
        SLEEP_THREAD
    }
    
    static class RunThread extends Thread {
        private final long runtime;

        public RunThread(long runtime) {
            this.runtime = runtime;
        }

        @Override
        public void run() {
            long startTime = System.currentTimeMillis();
            long endTime = startTime + runtime;
            while (System.currentTimeMillis() < endTime) {}
        }
    }

    static class SleepThread extends Thread {
        private final long runtime;

        public SleepThread(long runtime) {
            this.runtime = runtime;
        }

        @Override
        public void run() {
            try {
                Thread.sleep(runtime);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    
    public static void runHoldThread(ThreadType threadType, long holdTime, int number) {

        long startTime = System.currentTimeMillis();
        System.out.println("start");
        Thread[] threadArray = new Thread[number];

        for (int i = 0; i < number; i++) {
            switch (threadType) {
                case RUN_THREAD:
                    threadArray[i] = new RunThread(holdTime);
                    break;
                case SLEEP_THREAD:
                    threadArray[i] = new SleepThread(holdTime);
                    break;
            }
        }

        System.out.println("create complete");
        long createThreadOverTime = System.currentTimeMillis();

        for (Thread thread : threadArray) {
            thread.start();
        }
        System.out.println("all started");
        long callOverTime = System.currentTimeMillis();

        for (Thread thread : threadArray) {
            try {
                thread.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        long endTime = System.currentTimeMillis();

        System.out.printf("调用 耗时:%d ms , 等待耗时: %d ms ,共耗时 %d ms", callOverTime - createThreadOverTime, endTime - callOverTime, endTime-startTime);
    }

    @Test
    public void threadTest() {

        String pid = ManagementFactory.getRuntimeMXBean().getName().split("@")[0];
        System.out.printf("MAC 查看进程命令:\nps aux -M %s\ntop -pid %s\n", pid, pid);

//        runHoldThread(ThreadType.SLEEP_THREAD, 60000, 1);
//        runHoldThread(ThreadType.SLEEP_THREAD, 60000, 101);
//        runHoldThread(ThreadType.SLEEP_THREAD, 60000, 501);
//        runHoldThread(ThreadType.SLEEP_THREAD, 60000, 1001);
//        runHoldThread(ThreadType.RUN_THREAD, 60000, 1);
//        runHoldThread(ThreadType.RUN_THREAD, 60000, 101);
//        runHoldThread(ThreadType.RUN_THREAD, 60000, 501);
        runHoldThread(ThreadType.RUN_THREAD, 60000, 1001);
    }
}
Golang
package gmp

import (
   "fmt"
   "os"
   "sync"
   "testing"
   "time"
)

type RoutineType string

const (
   RunRoutine   RoutineType = "RunRoutine"
   SleepRoutine RoutineType = "SleepRoutine"
)

func TestGoroutine(t *testing.T) {
   pid := os.Getpid()
   fmt.Printf("MAC 查看进程命令:\nps aux -M %d\ntop -pid %d\n", pid, pid)
   //创建 n 个协程,每个空转 m秒

   //runGoroutine(SleepRoutine, time.Second*60, 1)
   //runGoroutine(SleepRoutine, time.Second*60, 101)
   //runGoroutine(SleepRoutine, time.Second*60, 501)
   //runGoroutine(SleepRoutine, time.Second*60, 1001)
   //runGoroutine(SleepRoutine, time.Second*60, 1000001)
   //runGoroutine(RunRoutine, time.Second*60, 1)
   //runGoroutine(RunRoutine, time.Second*60, 101)
   //runGoroutine(RunRoutine, time.Second*60, 501)
   //runGoroutine(RunRoutine, time.Second*60, 1001)
   runGoroutine(RunRoutine, time.Second*60, 1000001)
}

//运行协程
func runGoroutine(routineType RoutineType, singleRunningTime time.Duration, number int) {
   startTime := time.Now()
   var waitGroup sync.WaitGroup

   for i := 0; i < number; i++ {
      waitGroup.Add(1)
      switch routineType {
      case RunRoutine:
         go runRoutine(singleRunningTime, &waitGroup)
      case SleepRoutine:
         go sleepRoutine(singleRunningTime, &waitGroup)
      }
   }

   callOverTime := time.Now()
   waitGroup.Wait()
   runOverTime := time.Now()
   callDuration := callOverTime.Sub(startTime).Milliseconds()
   waitDuration := runOverTime.Sub(callOverTime).Milliseconds()

   fmt.Printf("调用 耗时:%d ms , 等待耗时: %d ms", callDuration, waitDuration)
}

//空转协程
func runRoutine(runningTime time.Duration, waitGroup *sync.WaitGroup) {
   defer waitGroup.Done()
   timeStart := time.Now()
   endTime := timeStart.Add(runningTime)
   for time.Now().Before(endTime) {
   }
}

//sleep协程
func sleepRoutine(runningTime time.Duration, waitGroup *sync.WaitGroup) {
   defer waitGroup.Done()
   time.Sleep(runningTime)
}
Java19 虚拟线程原理介绍及实现 本文介绍了 Java 线程模型、Java 虚拟线程的使用、原理和适用场景,并与流行的 Go 协程 进行了比较,也发现了两种实现方式的相似之处,希望对大家理解 Java 虚拟线程有所帮助。 阅读详情

相关推荐

GO 的goroutine(协程)和thread(线程)有什么区别

Thread 线程 在传统的web编程中,经常要用到多线程。比如 java,来一个websocket 即开启一个thread(线程)。 而thread的数目是有限的,一般的电脑可以同时开的thread数量大概几千个。而GO语言可以开启的goroutine,却可以达到几百万个,因此很显然goroutine不等于thread。 那么Thread和Goroutine的区别是什么? Thread,即多个程...

NikoKVCS的专栏 4062

Java的虚拟线程和go的协程哪个好

那是有一些争议的问题。 虚拟线程和协程都是轻量级的线程,它们可以帮助开发人员实现并发编程,但是它们的工作原理和用途略有不同。 Java的虚拟线程是在Java虚拟机内部实现的,它们可以帮助提高Java程序的执行效率,但是它们不能跨越多个处理器或核心执行。 相反,Go的协程是在操作系统内部实现的,它们可以跨越多个处理器或核心执行,并且Go的协程有更灵活的内存管理机制,但是它们的执行效率可能不如虚拟线程...

weixin_35756373的博客 1630

Java撮合引擎VS Golang撮合引擎:50万TPS差距的背后!为何Golang性能提升10倍?

摘要: Java与Golang在高频交易撮合引擎中的性能差距显著。Golang凭借轻量级协程(2KB/协程)、原生通道(Channel)和无锁设计,实现50万+ TPS与10ms延迟,而Java受限于线程模型(2MB/线程)、GC停顿及锁竞争,性能瓶颈明显(30万TPS,50ms延迟)。案例显示,Golang方案可提升吞吐量60%、降低内存占用,代码更简洁。未来Java需突破线程与GC限制,或探索混合语言架构以应对百万级并发挑战。(150字)

java专栏 1330

Java21新特性-虚拟线程

是轻量级线程(类似于 Go 中的 “(Goroutine)”),可以减少编写、维护和调度高吞吐量并发应用程序的工作量。是可供调度的最小处理单元,它与其他类似的处理单元并发运行,并且在很大程度上是独立运行的。线程()有两种,和。

听得到微笑的博客 1万+

Go有协程,Java有虚拟线程,聊一聊Java Virtual Threads

通过修改同步块 synchronized 来避免频繁和长时间的锁定,并使用 java.util.concurrent.locks.ReentrantLock来保护潜在长时间的I/O操作,该锁以类似于同步代码中的隐式锁的方式控制多个线程对共享资源的访问。在该示例中,我们创建了一个 Semaphore 对象,并在一个线程中使用 acquire() 方法获取许可证,模拟对共享资源的访问。仔细考虑ThreadLocal的使用,因为您的应用程序中可能有很多虚拟线程,它们共用平台线程(即原来的线程)的内存空间。

程序员野蛮成长 996

激光可燃气体传感器:核心技术环节分析

激光可燃气体传感器核心技术涵盖七个维度:1)TDLAS光谱吸收与调制技术(检测下限ppm级);2)DFB激光器与双闭环温控系统(波长稳定性±0.0036nm);3)微弱信号处理技术(信噪比提升60dB);4)环境补偿算法(温压补偿误差<±1%);5)本质安全防爆设计(ExiaIICT4Ga等级);6)智能边缘计算(STM32L476芯片);7)多重性能验证(响应时间<1秒)。通过微型化、多气体检测等创新,该技术已在工业安全等领域替代传统方案,实现高精度检测。(149字)

上市公司前技术负责人,20 年软硬件深耕 + 百人研发团队管理经验,名校理工科背景加持。从技术攻坚到团队掌舵,沉淀海量项目实战与管理心得,专注分享软硬件干货、疑难问题解决方案,既是靠谱知识传播者,也盼链接优质项目共成长。 1047

Java19 虚拟线程 VS Go 协程 的吞吐量

Java19 带来了 Java 新特性 —— 虚拟线程。Java 新特性之前,Go 语言的协程在并发编程领域得到友好的口碑。随着国内 Go 语言的快速发展与推广,协程好像成为了一个世界上最好语言的必备特性之一。Java19 虚拟线程就是来弥补这个空白的。

ejinxian的专栏 2742

centos7下100T存储扩容(LVM)至150T

查看新增磁盘情况lsblk,fdisk -l [root@localhost ~]# lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT sr0 11:0 1 4.2G 0 rom vda 252:0 0 80G 0 disk ├─vda1 252:1 0 1G 0 part /boot └─vda2 252:2

tiyager的博客 1025

用户级线程 vs 内核级线程:如何选择?从Go协程到Java虚拟机的实战对比

本文深入解析了用户级线程与内核级线程的核心差异,并结合Go协程与Java虚拟线程的实战案例,探讨了现代高并发架构下的选择策略。文章指出,用户级线程轻量高效但存在阻塞风险,内核级线程并行性好但开销大。现代语言普遍采用M:N混合模型以兼顾两者优势,并针对I/O密集型、计算密集型及混合型场景提供了具体的选择与调优建议。

rock5的博客 222

LeRobot SO-ARM100 学习笔记(2) diffusion module

对 lerobot 中的 diffusion policy 进行基本的代码阅读

mikhailbran的博客 1588

从扇束到平行束:等角重排算法在CT重建中的核心原理与MATLAB实践

本文深入解析了CT图像重建中等角扇束重排算法的核心原理与MATLAB实现。通过将实际采集的扇束投影数据,利用几何映射和两次关键插值,转换为适用于经典滤波反投影算法的平行束数据,打通了高效重建的关键路径。文章结合Shepp-Logan模型仿真,提供了完整的MATLAB代码实践,并分析了源-物距、采样率等关键参数对重建质量的影响。

cnn8visionary的博客 648

协程 vs 线程:为什么Go语言比Java更适合高并发场景?

本文深入对比了Go语言的协程(goroutine)与Java线程在高并发场景下的核心差异。重点分析了Go基于用户态的M:N调度模型、轻量级goroutine(初始栈仅2KB)以及netpoller非阻塞I/O机制如何实现数十万级并发,而Java线程因1:1映射内核线程、固定MB级栈内存及昂贵上下文切换,在资源消耗和性能上处于劣势。文章指出,Go通过“通过通信共享内存”的Channel哲学,为高并发I/O密集型服务提供了更高效、简洁的开发范式。

a0b1c2d3的专栏 476

如何评估一颗 AI 芯片的真实性能?TOPS、FPS 与 Token/sec 全解析

AI 芯片在实际部署中,其理论峰值性能往往无法反映真实执行效率。如何科学评估一颗 AI 芯片的“真实性能”,已成为芯片选型与系统集成环节中的关键技术问题。本文从工程实战角度出发,深入拆解当前常用性能评估指标(TOPS、FPS、Token/sec)背后的定义逻辑与使用陷阱,并结合推理模型部署与执行路径,系统讲解 AI 芯片在不同场景下的性能验证方法。通过对芯片算力-功耗-调度三维关系的分析,读者将掌握评估一颗 AI 芯片是否“跑得动业务”的核心判断能力。

努力分享一些人工智能、计算机视觉、影像等相关的知识干货! 3397

用户级线程 vs 内核级线程:如何选择?从Go语言协程到Java虚拟机的实战分析

本文深入分析了用户级线程(ULT)与内核级线程(KLT)的核心差异及适用场景,结合Go语言协程和Java虚拟机的实战案例,帮助开发者根据计算密集型或IO密集型需求选择合适的线程模型。文章详细对比了两种模型在创建耗时、上下文切换、内存占用等关键指标上的表现,并提供了混合架构的最佳实践建议。

weixin_29207533的博客 208

告别路径打架!用Python实现CBS算法搞定仓库机器人调度(附完整代码)

本文详细介绍了如何使用Python实现CBS(Conflict-Based Search)算法解决仓库机器人调度中的路径冲突问题。通过多智能体路径规划(MAPF)技术,有效避免AGV在智能仓库中的碰撞和死锁,提供完整代码实现和工业场景优化技巧,帮助开发者快速构建高效的机器人调度系统。

weixin_30275415的博客 331

【ROS2】Arduino系列之机器人底盘实现

介绍ros中提供的一个已经封装了的模块: ros_arduino_bridge,该模块由下位机驱动和上位机控制两部分组成,通过该模块可以更为快捷、方便的实现自己的机器人平台

guilin 1486

Go与Java语言特性及并发模型深度对比

编程语言的设计哲学直接影响其类型系统、内存管理和并发模型等核心特性。Go语言采用结构化类型系统和基于接口的隐式实现,相比Java的名义类型系统具有更好的扩展性。在并发模型方面,Go的goroutine和channel机制实现了轻量级线程通信,而Java依赖传统的线程池和锁机制。内存管理上,Java的GC经过长期优化适用于复杂场景,Go则通过逃逸分析等技术实现高效内存分配。这两种语言在微服务架构、云计算等现代应用场景中各具优势,Go适合高并发I/O密集型任务,Java则更擅长计算密集型业务。理解这些底层原理差

weixin_34199764的博客 215

回归预测 | MATLAB实现TCN时间卷积神经网络多输入单输出回归预测

回归预测 | MATLAB实现TCN时间卷积神经网络多输入单输出回归预测

机器学习之心的博客,关注并私信文章链接,获取对应文章源码和数据。 2492

Go协程与Java虚拟线程对比:高并发场景下的调度、实操与选型指南

高并发服务架构中,传统线程模型因内存占用高、上下文切换开销大而逐渐成为瓶颈。用户态线程作为一种轻量级调度方案,正被主流语言广泛采用:Go 通过 goroutine 内建并发能力,Java 则在 JDK 21 中正式引入虚拟线程。理解两者底层调度机制(GMP 模型与载体线程池)以及阻塞处理方式,是评估技术价值的关键。这两类技术都擅长 IO 密集型场景,可显著提升吞吐量,但在 CPU 密集任务中并无优势;此外,内存占用、通信模型与生态兼容也直接影响落地效果。本文从高并发调度原理出发,结合代码示例和实战踩坑,对比

weixin_32325225的博客 230

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

Go语言极简高并发实战:10行代码实现百万级任务调度,吊打Java线程池

云原生时代,Go已经成为后端高并发服务首选语言。不需要复杂的并发知识,极简代码就能实现工业级并发能力。后续我会更新Go生产级任务池完整版,包含监控、重试、优雅停机功能,感兴趣可以关注。

2609_96322798的博客 167

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

进程与线程:核心概念、性能对比与实战应用

进程和线程是操作系统中最基础的并发执行单元,理解它们的本质差异对开发高性能应用至关重要。进程作为资源分配的基本单位,拥有独立的内存空间和系统资源,通过IPC机制实现通信;而线程作为轻量级执行流,共享进程资源但需要处理同步问题。在性能方面,线程上下文切换开销仅为进程的1/10,这使得线程池技术成为高并发服务的核心实现方式。实际开发中,合理运用进程隔离特性和线程共享模型,能够有效解决内存泄漏、线程阻塞等问题。特别是在Android开发、微服务架构等场景下,掌握进程与线程的调度策略和资源管理机制,对提升系统稳定性

weixin_31423955的博客 20

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

k6与JMeter性能测试工具对比与选型指南

性能测试是确保软件系统可靠性的关键技术,通过模拟真实用户负载来验证系统性能指标。现代性能测试工具主要采用协程或线程模型实现并发,其中k6基于Go语言的协程架构具有极高的资源效率,而JMeter则凭借Java线程模型和丰富功能集长期占据企业级测试领域。从技术原理看,k6的轻量级特性使其特别适合集成到CI/CD流程和云原生环境,而JMeter的全面协议支持和可视化界面则降低了非技术用户的使用门槛。在实际工程实践中,开发者常需要根据项目需求在两者间做出选择:现代Web API测试和持续集成场景更适合k6,而复杂企

weixin_28826521的博客 8

深入解析并发编程中的阻塞与非阻塞机制

并发编程是现代软件开发的核心技术,涉及多任务协调与资源分配。阻塞与非阻塞是两种基础I/O模型:阻塞调用会挂起线程直到操作完成,而非阻塞调用立即返回允许线程继续执行。理解这两种机制对构建高性能系统至关重要,特别是在网络编程和服务器开发中。通过多线程阻塞模型或单线程非阻塞模型(如select/epoll),开发者可以应对不同场景的并发需求。现代语言如Python的asyncio、Go的goroutine和Rust的所有权系统,都提供了更高级的并发抽象。掌握这些技术能有效提升系统吞吐量,应对高并发场景下的线程颠簸

weixin_30219613的博客 230

go协程goroutine与Java多线程比较

引言:个人理解的线程,协程和单,多核线程  1. 单核CPU上运行的多线程程序, 同一时间只能一个线程在跑, 系统帮你切换线程而已(cpu时间切片), 系统给每个线程分配时间片来执行, 每个时间片大概10ms左右, 看起来像是同时跑, 但实际上是每个线程跑一点点就换到其它线程继续跑,效率不会有提高的,切换线程反倒会增加开销(线程的上下文切换),宏观的可看着并行,单核里面只是并发,真正执行的一个cpu

Anteoy的博客 1万+

k6与JMeter性能测试工具全面对比与应用指南

性能测试是确保软件系统稳定性的关键技术,通过模拟真实用户行为来识别系统瓶颈。主流工具如k6和JMeter采用不同架构设计:k6基于Go语言实现轻量级协程模型,适合云原生环境和高并发场景;JMeter采用Java多线程架构,以丰富的协议支持和GUI操作见长。在持续集成实践中,k6凭借低资源消耗和代码化脚本更易融入DevOps流程,而JMeter则擅长传统企业级应用的复杂测试需求。开发者可根据项目特点选择工具——现代Web服务推荐k6+Grafana实现实时监控,传统系统则可利用JMeter的插件生态完成深度测

weixin_28677451的博客 8

Golang协程

text商场 (计算机)├── 店铺A (进程A)│ ├── 正式员工1 (线程1) -- 由【商场总管理处】(内核态)调度│ ├── 正式员工2 (线程2) -- 由【商场总管理处】(内核态)调度│ └── 一群实习生 (协程) -- 由【店长】(用户态调度器)管理,跑在几个正式员工身上├── 店铺B (进程B)流程演进:一个店铺只有一个员工(单线程进程),效率低。一个店铺雇多个员工(多线程进程),效率高了,但雇佣和管理成本(创建/切换线程的开销)也高了。

qq_48512649的博客 919
上一篇: k8s常用命令
下一篇: Golang小数点保留
RobertLee~~~~~~~~
博客等级 码龄18年 14粉丝 43原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值