• Home
  • 归档
文章检索 作品与友邻 关于我
暴君乔博客
Home 归档

Java并发从0开始到0.001

发布于: 2021-07-04
更新于: 2023-07-09
文章目录
  1. Java 并发
    1. 多线程
    2. volatie
    3. CAS
    4. AQS
    5. 锁
    6. 线程池

Java 并发

多线程

多线程实现方式

Java多线程实现方式

使用无界队列线程池 OOM 情况

// 创建无界队列
ExecutorService threadPool=Executors.newFixedThreadPool(100);

// 核心参数为以下内容
public ThreadPoolExecutor(int corePoolSize,
                            int maximumPoolSize,
                            long keepAliveTime,
                            TimeUnit unit,
                            BlockingQueue<Runnable> workQueue) {
    this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
            Executors.defaultThreadFactory(), defaultHandler);
}

无界线程队列

volatie

保证可见性和有序性,有序性主要是指防止指令重排(指令重排主要是指 jvm 优化时,可能会将未完全初始化的对象对外使用,即将指向 null 的对象对外使用,导致 NPE,而 volatie 避免了重排)
想了解 volatie 首先先了解 Java 线程内存模型

Java 线程内存模型

每个线程都有自己的工作内容,以及一个共享的主内存。

连环炮开始:

提问 答
为什么要让每个线程都用一个工作内存保留主内存的副本以供读取? 如果每次线程都要 CPU 从主存中提取,导致性能差,主存的读写也极为麻烦,所以如果每个都配置,相当于高速的本地缓存,带来性能提升
每个线程自己拥有一份内存副本有什么问题? 假如线程 1、线程 2 同时持有了 test=1 的值,这时线程 1 想改为 test=5,但是它只是改了自身副本的 1 为 5,没有改到主存以及线程 2 里面的内存副本
那么怎么解决上述的问题 加一个 volatie 标识变量,这样子每次修改时强制把最新的值刷回主内存,同时让其他线程的变量缓存直接失效过期,不允许再次读取和使用

CAS

Compare And Set 比较后再设置
AtmoicInteger 原子类底层使用的不是以前的锁机制,而是无锁化的 CAS 机制,通过 CAS 机制保证了多线程修改一个数值的安全性。

大致流程:

可以看到假如并发很严重时,会导致有很多线程一直自旋,可以上新家伙 LongAdder,大致原理是把 CAS 分散到一个 Cell 数组上,通过对 Cell 数值分组的 CAS 操作,提升了 CAS 总得效率,吞吐量。

当你需要当前累加总值时,会将 Cell 数组内的累加总值累加起来返回,但注意此处的 sum 函数不是互斥的,即不是准确的当前值。

    /**
     * Returns the current sum.  The returned value is <em>NOT</em> an
     * atomic snapshot; invocation in the absence of concurrent
     * updates returns an accurate result, but concurrent updates that
     * occur while the sum is being calculated might not be
     * incorporated.
     *
     * @return the sum
     */
    public long sum() {
        Cell[] cs = cells;
        long sum = base;
        if (cs != null) {
            for (Cell c : cs)
                if (c != null)
                    sum += c.value;
        }
        return sum;
    }

AQS

AbstractQueuedSynchronizer 通过一个 state 的 int 变量记录加锁状态,以及一个记录当前线程是谁,实现可重入锁的关键功能。同时还有一个等待锁的队列,以及可重入锁的概念,当前线程可以反复上锁,即改变 state 的值直到 Integer.MAX_VAL

AQS

锁

公平锁

指加锁线程按照 FIFO 的顺序进行获取锁

非公平锁

像秒杀一样先到先得

ReentrantLock

以及大部分的并发包都是默认非公平策略的

也可以通过 new ReentrantLock(true)开启公平策略。

非公平的原理:
抢占锁时,不会管等待队列是否有线程,大家一起抢。

公平的原理:
抢占锁时,先看等待队列是否为空?如果不为空,则自觉插入到队列的尾部等待前面的线程处理完。

Condition

相对于Object monitor锁,这里实现的内容主要是通过Lock来实现await和signal内容

Condition
+await
+await
+awaitNanos
+awaitUninterruptibly
+awaitUntil
+signal
+signalAll

线程池

ThreadPoolExecutor


    /**
     * Creates a new {@code ThreadPoolExecutor} with the given initial
     * parameters.
     *
     * @param corePoolSize the number of threads to keep in the pool, even
     *        if they are idle, unless {@code allowCoreThreadTimeOut} is set
     * @param maximumPoolSize the maximum number of threads to allow in the
     *        pool
     * @param keepAliveTime when the number of threads is greater than
     *        the core, this is the maximum time that excess idle threads
     *        will wait for new tasks before terminating.
     * @param unit the time unit for the {@code keepAliveTime} argument
     * @param workQueue the queue to use for holding tasks before they are
     *        executed.  This queue will hold only the {@code Runnable}
     *        tasks submitted by the {@code execute} method.
     * @param threadFactory the factory to use when the executor
     *        creates a new thread
     * @param handler the handler to use when execution is blocked
     *        because the thread bounds and queue capacities are reached
     * @throws IllegalArgumentException if one of the following holds:<br>
     *         {@code corePoolSize < 0}<br>
     *         {@code keepAliveTime < 0}<br>
     *         {@code maximumPoolSize <= 0}<br>
     *         {@code maximumPoolSize < corePoolSize}
     * @throws NullPointerException if {@code workQueue}
     *         or {@code threadFactory} or {@code handler} is null
     */
    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {
        if (corePoolSize < 0 ||
            maximumPoolSize <= 0 ||
            maximumPoolSize < corePoolSize ||
            keepAliveTime < 0)
            throw new IllegalArgumentException();
        if (workQueue == null || threadFactory == null || handler == null)
            throw new NullPointerException();
        this.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = threadFactory;
        this.handler = handler;
    }
key val
corePoolSize 核心线程,哪怕当前状态为 idle 闲置,也会保留,除非定义了 allCoreThreadTimeOut
maximumPoolSize 最大线程数
keepAliveTime 当线程数大于核心线程时,闲置的线程如果超过了等待时间则会 kill 掉
workQueue 持有着即将执行的工作队列。只会持有通过 execute()提交的 Runnable 的任务
threadFactory 通过线程工厂创建新的线程
handler 当执行阻塞时,比如说线程池满了,等待队列满了,这时应选的拒绝策略
Java并发从0开始到0.001
/archives/4ed0a142/
作者
tyrantqiao
发布于
2021-07-04
更新于
2023-07-09
许可协议
CC BY-NC-SA 4.0
赏

蟹蟹大佬的打赏,大家一起进步

支付宝
微信
  • Java

扫一扫,分享到微信

微信分享二维码
Java基础知识从0.1到0.000001
复杂度计算
© 2026 tyrantqiao 本站总访问量次 本站访客数人次 载入天数...载入时分秒...
  • 文章检索
  • 作品与友邻
  • 关于我

展开标签

  • 随笔
  • 旅行
  • Java
  • 面经
  • 源码
  • 架构
  • Hadoop
  • 计算机网络
  • 技术
  • IDEA
  • maven
  • JDK
  • Linux
  • MySQL
  • 性能
  • 数据库
  • Redis
  • MQ
  • Spring
  • SquirrelFin
  • 记账
  • Android
  • 个人财务
  • TIDB
  • unity
  • chatgpt
  • 前端
  • Vue
  • Git
  • shadowsocks
  • Hexo
  • 问题排查
  • 业务
  • JVM
  • 算法
  • nginx
  • ssh
  • Python
  • 爬虫
  • test
  • vim
  • 影视剧
  • 中间件
  • 事务
  • 表达
  • 运动
  • mybatis
  • 域名
  • AI
  • 产品
  • 家装
  • 土巴兔
  • github
  • 软件
  • 个人项目
  • Leaves
  • 幽默
  • 穿搭
  • 画画
  • 缓存
  • 摄影
  • 设计模式
  • c
  • 课程设计
  • 调酒
  • 数学

Collection

作品与友邻

我做的小工具、朋友的站点和一些长期值得回访的灵感来源。

  • 土 土巴兔 AI 导购交互演示 可点击体验用户导购、平台运营、装修公司、材料商及 AI 话术知识库的多端增长流程。 /demos/tubatu-ai-guide/
  • L Leaves 行程记录 我做的行程记录页面小工具,用来沉淀旅行路线、日程安排和途中的灵感。 https://leaves.tyrantqiao.com/
  • 本 本网站主题yilia设计者的主页 http://litten.me/
tyrantqiao的头像

tyrantqiao

github rss qq mail facebook linkedin

About

关于我

代码、海浪和持续折腾,都是生活的一部分。

<div class="aboutme-card"> <p class="aboutme-eyebrow">tyrantqiao</p> <h3>Java 全栈开发</h3> <p>常年和 Java、后端服务、前端工程、数据与部署打交道,喜欢把复杂问题拆开、写清楚,也把踩坑过程整理成文章留给后来的人。</p> <div class="aboutme-tags"> <span>Java</span> <span>Full Stack</span> <span>Backend</span> <span>Frontend</span> <span>Extreme Sports</span> </div> <p>工作之外偏爱冲浪等极限运动,享受在浪上找平衡,也享受在代码里找边界。</p> <div class="aboutme-contact"> <a href="mailto:[email protected]">Gmail</a> <a href="mailto:[email protected]">QQ Mail</a> </div> </div>