程序员求职经验分享与学习资料整理平台

网站首页 > 文章精选 正文

并发编程体系概述

balukai 2025-03-05 13:20:17 文章精选 6 ℃

作者:京东自有品牌 周振

类别

定义

特点

应用场景

Java中的使用

进程 (Process)

计算机程序在操作系统中执行的实例

- 独立性强、 拥有独立的内存空间、 创建和销毁开销大- 进程间通信复杂

- 独立的应用程序 - 高隔离性任务,如数据库服务器

- Java应用程序运行在JVM进程中 - 通过ProcessBuilder调用外部进程

线程 (Thread)

进程中的执行单元,共享进程的内存空间和资源

- 轻量级- 共享内存- 创建和销毁开销较小- 并发执行

- 多任务处理,如GUI应用 - 并行计算

- 使用java.lang.Thread类 - 利用java.util.concurrent包 - 线程池(ExecutorService)管理线程

协程 (Coroutine)

更轻量级的并发单元,通过用户态上下文切换实现

- 更轻量级- 非抢占式调度- 高效I/O处理

- I/O密集型任务,如网络爬虫 高并发Web应用

- Java本身不直接支持 - 使用Kotlin协程实现异步编程

协程在处理高并发和I/O密集型任务时,具有明显的优势,尤其是在编写异步代码时更加简洁和高效。然而,对于CPU密集型任务和传统的多任务处理,线程仍然是一个成熟且有效的选择。

选择协程还是线程,取决于具体的应用场景和需求。随着Kotlin协程在Java生态系统中的普及,越来越多的中间件和框架开始支持协程。

但是并不一定要使用协程,使用基于多线程的分布式并发框架也可以实现类似的效果、如akka、Spring WebFlux等。


多线程知识汇总

基础知识

具体可以查找我之前博客:
https://blog.csdn.net/Zzhou1990/article/details/106008171





响应式编程



特性

CompletableFuture

Stream

Optional

Observable (RxJava 1)

Observable (RxJava 2)

Flowable (RxJava 2)

Flux

Akka Streams

可组合的

惰性的

可重用的

(部分)

异步的

可缓存的

(需显式调用)

(需显式调用)

(需显式调用)

(需显式调用)

推送的

背压的

操作符融合

Show me code

获取时间的并发问题

总结起来原因是System.currentTimeMillis调用了gettimeofday()

调用gettimeofday()需要从用户态切换到内核态;

gettimeofday()的表现受Linux系统的计时器(时钟源)影响,在HPET计时器下性能尤其差;

系统只有一个全局时钟源,高并发或频繁访问会造成严重的争用

所以中间件在获取时间时候会有一个单例线程。

分析文章地址
http://pzemtsov.github.io/2017/07/23/the-slow-currenttimemillis.html


阿里sentine获取时间工具类

public final class TimeUtil {

    private static volatile long currentTimeMillis;

    static {
        currentTimeMillis = System.currentTimeMillis();
        Thread daemon = new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    currentTimeMillis = System.currentTimeMillis();
                    try {
                        TimeUnit.MILLISECONDS.sleep(1);
                    } catch (Throwable e) {

                    }
                }
            }
        });
        daemon.setDaemon(true);
        daemon.setName("sentinel-time-tick-thread");
        daemon.start();
    }

    public static long currentTimeMillis() {
        return currentTimeMillis;
    }
}


json转换的性能问题


    List vendorList = vendorInfoMapper.findVendorList();
    log.info("日志输出:{}", JSONUtils.toJSONString(vendorList));

    if(log.isInfoEnabled()){
        log.info("日志输出:{}", JSONUtils.toJSONString(vendorList));
    }


class User {
    private long id;
    private String name;
    private String email;
}

  public User getUserInfoLowPerformance(long userId) {
        String key = USER_INFO_KEY + ":" + userId;
        String jsonUser = (String) redisTemplate.opsForValue().get(key);
        if (jsonUser == null) {
            return null;
        }
        return new Gson().fromJson(jsonUser, User.class);
    }


    public User getUserInfo(long userId) {
   
        Map userInfoMap = redisTemplate.opsForHash().entries(key);
        if (userInfoMap.isEmpty()) {
            return null;
        }

        user = new User();
        user.setId((Long) userInfoMap.get("id"));
        user.setName((String) userInfoMap.get("name"));
        user.setEmail((String) userInfoMap.get("email"));
        //...
     }



循环处理

循环会将低性能代码放大,主要查看以下,使用异步或非核心操作不是必须在响应前完成。

查找数据O(1)、使用IO网络、缓存、磁盘、使用cpu等操作


流式编程

流程编程、caffeine缓存、批处理优化;减少阻塞等待

case改造案例:50ms -> 15ms


UMP和泰山

UMP秒级监控、强大泰山整合了UMP、链路追踪、硬件监控、负载均衡等,内部优秀的工具帮助监控性能问题;

通过UMP秒级监控作为入口,秒级监控需手动开启,限制接口50个




Tp99/Tp999;可用率等;下钻查看每个机器的流量,这些可以根据机器配置在NP平台调整权重以及负载策略,继续根据机器查看





生态和体系

并发&IO









并发&内存&CPU

JVM内存模型,不同的jdk版本;确保内存可见性和指令重排序的规则、以及线程的调度

JVM gc参数设置、包括gc频率、相关参数线程数

用户态和内核态切换。


并发&锁

选择不同的锁,会对并发产生比较大的影响;

锁分类 : 互斥锁、自旋锁、读写锁、乐观锁、悲观锁、锁分段(表锁、行锁、间隙锁)、无锁cas

https://blog.csdn.net/Zzhou1990/article/details/114393298?spm=1001.2014.3001.5501

并发&中间件

数据库、缓存、断路器(限流、降级、合并)、服务间调用、配置中心、链路追踪、日志、JMQ

基数和标准:一次Tcp连接时间、一次Http连接时间

如机器配置4核8g mysql, qps和tps 响应时间根据sql复杂度从几十ms~ns不等

如机器配置8核32C redis qps 响应时间从nms~100ms

其他:

堆外内存

减少gc、序列化和反序列化。

字节码增加

Ask gpt4.0 字节码增强如何提高代码性能

缓存行

64Kb、Disruptor、伪共享

https://tech.meituan.com/2016/11/18/disruptor.html

类似概念磁盘顺序读写

局部性原理和分支优化

空间局部性优化:使用数组、合理模型结构

较少分支、分支展开、条件合并


性能分析、火焰图
http://jagile.jd.com/shendeng/article/detail/1680

如何写出让CPU跑得更快的代码 = 如何写出让CPU缓存命中率更高的代码


并发不只是并发,他还是个策略问题:处理数据的时候选择合适的策略,可能数据很快就会跑出来。

问下chatgpt:从kafka架构设计角度说说高并发怎么实现、用户态和内核态、

Tags:

最近发表
标签列表