![](https://img-blog.csdnimg.cn/20201014180756923.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
多线程与高并发
文章平均质量分 87
morris131
这个作者很懒,什么都没留下…
展开
-
JDK8中ConcurrentHashMap源码阅读
数据结构常量:private static final int MAXIMUM_CAPACITY = 1 << 30; // 元素的最大个数private static final int DEFAULT_CAPACITY = 16; // 数组的默认初始长度,必须是2的幂次方static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; // 数组的最大长度private static final int DEFAULT_CON原创 2021-03-17 14:02:43 · 2760 阅读 · 0 评论 -
JDK8中HashMap源码分析
JDK8对HashMap进行了一些修改,最大的不同就是利用了红黑树,所以其由**数组+(链表或红黑树)**组成。在JDK7及之前的HashMap中,根据key查找value时,根据hash值我们能够快速定位到数组具体下标位置处的链表,但是之后的话,需要顺着链表一个个比较下去才能找到我们需要的,时间复杂度取决于链表的长度,为O(n)。为了降低这部分的开销,在JDK8中,当链表中的元素超过了8个以后,会将链表转换为红黑树,在这些位置进行查找的时候可以降低时间复杂度为 O(logN)。数据结构JDK8中H原创 2021-03-15 17:39:42 · 772 阅读 · 0 评论 -
JDK7中HashMap源码分析
由于目前大部分都是使用JDK8进行开发,JDK7 HashMap的源码不好找,这里贴上JDK7 HashMap的源码在线阅读地址:__java7 HashMap__,方便大家学习。数据结构HashMap内部采用数组+单向链表的数据结构来实现。HashMap内部维护一个数组,然后数组中每个元素是一个个单向链表。HashMap的几个关键属性:static final int DEFAULT_INITIAL_CAPACITY = 16; // 默认的初始容量是16,必须是2的幂。static fina原创 2021-03-15 16:57:07 · 907 阅读 · 0 评论 -
阻塞队列,有界队列,无界队列
在并发编程中,有时候需要使用线程安全的队列。如果要实现一个线程安全的队列有两种方式:一种是使用阻塞算法,另一种是使用非阻塞算法。使用阻塞算法的队列可以用一个锁(入队和出队用同一把锁)或两个锁(入队和出队用不同的锁)等方式来实现。非阻塞的实现方式则可以使用自旋+CAS的方式来实现。基本概念阻塞队列与非阻塞队列阻塞队列(BlockingQueue)是一个支持两个附加操作的队列。这两个附加的操作支持阻塞的插入和移除方法。支持阻塞的插入方法offer:当队列满时,队列会阻塞插入元素的线程,直到队列不满原创 2021-03-12 16:03:00 · 13132 阅读 · 3 评论 -
ReentrantLock重入锁的使用与源码分析
ReentrantLock的使用构造方法构造方法名说明ReentrantLock()创建一个非公平锁ReentrantLock(boolean fair)以给定的公平策略创建一个ReentrantLock的实例公平锁:公平锁能保证先获取锁的线程一定能先得到锁,避免饥饿,效率不是太高非公平锁:非公平锁不保证谁先获取谁先得到锁,会产生饥饿线程,效率高实例方法实例方法名说明int getHoldCount()返回当前线程获取此锁的次数原创 2021-03-09 16:37:10 · 6440 阅读 · 2 评论 -
Semaphore信号量的使用与源码分析、使用wait-notify手写实现
Semaphore(信号量)是用来限制资源(如线程)的并发数量。api方法名说明void acquire()从信号量获取1个许可证,一直阻塞到有许可证或被中断void acquire(int permits)从信号量获取permits个许可证,一直阻塞到有许可证或被中断void acquireUninterruptibly()从信号量获取1个许可证,一直阻塞到有许可证,不可被中断void acquireUninterruptibly(int permits)原创 2021-02-26 11:51:15 · 3280 阅读 · 1 评论 -
原子操作类的使用以及ABA问题的解决
原子操作类包括以下几类:基本类:AtomicInteger、AtomicLong、AtomicBoolean。引用类型:AtomicReference、AtomicStampedRerence、AtomicMarkableReference。数组类型:AtomicIntegerArray、AtomicLongArray、AtomicReferenceArray。属性原子修改器(Updater):AtomicIntegerFieldUpdater、AtomicLongFieldUpda原创 2021-02-24 16:53:39 · 4219 阅读 · 0 评论 -
Thread API详解
构造方法Thread类提供了丰富的构造方法,具体如下:Thread()Thread(Runnable target)Thread(Runnable target, String name)Thread(String name)Thread(ThreadGroup group, Runnable target)Thread(ThreadGroup group, Runnable target, String name)Thread(ThreadGroup group, Runnable tar原创 2021-02-22 13:46:51 · 2662 阅读 · 2 评论 -
线程的生命周期
线程的状态线程的生命周期中大体可分为以下6种状态:NEWRUNNABLEBLOCKEDWAITINGTIMED_WAITINGTERMINATED在Thread类中有个内部枚举类State用来表示线程的状态:public enum State { NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING, TERMINATED;}下面是线程各种状态之间的变换图:NEW(原创 2021-02-20 11:40:56 · 4086 阅读 · 2 评论 -
线程的实现方式
基本概念进程和线程进程(Process):程序运行资源分配的最小单位,进程内部有多个线程,会共享这个进程的资源。线程(Thread):CPU调度的最小单位,必须依赖进程而存在。并行和并发并行(Paralle):同一时刻,可以同时处理事情的能力。并发(Concurrent):与单位时间相关,在单位时间(如1s)内可以处理事情的能力。并发的意义与问题意义:充分利用cpu的资源,加快用户响应的时间。程序模块化,异步化。问题:线程共享资源,存在冲突,出原创 2021-02-19 11:12:38 · 1052 阅读 · 0 评论 -
volatile的底层原理与实现
volatile的底层原理volatile的两个作用:可见性防止指令重排序计算机的组成下图是一个典型的计算机结构图,计算机的组成主要包括CPU、存储器(内存)、IO(输入输出设备)。存储器的层次结构下图是计算机中存储器的层次结构,越靠近CPU,存储器的访问速度就越快,成本也越高,最快的存储器是CPU内部的寄存器。为什么会有存储器分级策略?从理论上来说,我们希望存储器速度快、体积小、空间大、能耗低、散热好、断电数据不丢失,成本低。但是在现实中,这些条件是无法同时满足的,比如存储器的体积原创 2020-10-24 13:01:55 · 28191 阅读 · 2 评论 -
Executors四大线程池工厂方法的使用
id: 1602583277163title: 四大线程池的使用date: 2020-10-13updated: 2020-10-13categories: 高并发与多线程tags:- 高并发与多线程Executors工厂方法的使用Executors提供了四个创建线程池的工厂方法,分别是:Executors.newSingleThreadExecutor()Executors.newFixedThreadPool()Executors.newCachedThreadPool()E.原创 2020-10-15 15:19:17 · 16512 阅读 · 0 评论 -
ThreadPoolExecutor线程池7个参数的含义、任务的提交、线程池的关闭和拒绝策略
ThreadPoolExecutor线程池的使用线程池的创建我们可以通过ThreadPoolExecutor来创建一个线程池。public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit,原创 2020-10-13 18:00:26 · 17709 阅读 · 1 评论 -
CyclicBarrier的使用与源码分析,手写实现
CyclicBarrier的使用与源码分析CyclicBarrier俗称栅栏,它可以让多个线程之间互相等待,直到所有线程都到达同一个同步点,然后再继续一起执行。CyclicBarrier默认的构造方法是CyclicBarrier(int parties),其参数parties表示屏障拦截的线程数量,每个线程都会调用await方法告诉CyclicBarrier我已经到达了屏障,然后当前线程被阻塞,当所有线程都到达了屏障,所有线程都被唤醒然后继续往下执行。CyclicBarrier的常用方法方法原创 2020-09-27 20:35:53 · 16193 阅读 · 1 评论 -
CountDownLatch的使用与源码分析、手写实现
CountDownLatch的使用与源码分析CountDownLatch俗称闭锁,它可以允许一个或多个线程等待其他线程完成指定操作后再运行。CountDownLatch的构造函数接收一个int类型的参数作为计数器,如果你想等待N个点完成,这里就传入N。当我们调用CountDownLatch的countDown方法时,N就会减1,CountDownLatch的await方法会阻塞当前线程,直到N变成零。由于countDown方法可以用在任何地方,所以这里说的N个点,可以是N个线程,也可以是1个线程里的原创 2020-09-25 14:12:21 · 12656 阅读 · 1 评论 -
ReentrantReadWriteLock读写锁源码分析
ReentrantReadWriteLock读写锁源码分析读写状态的设计ReentrantReadWriteLock也是通过自定义AQS(抽象队列同步器)实现。同步器内部只有一个状态,而读写锁需要维护两个状态:读状态与写状态。ReentrantReadWriteLock将同步器内部的状态state按位进行拆分:高16位代表读状态,低16位代表写状态。java.util.concurrent.locks.ReentrantReadWriteLock.Syncstatic final int SHAR原创 2020-09-24 11:39:09 · 21269 阅读 · 1 评论 -
AQS源码分析之中断与超时获取锁
AQS源码分析之中断与超时获取锁中断基础Thread.interrupt():对象方法,置中断标记为true。Thread.currentThread().isInterrupted():对象方法,返回线程当前的中断标记状态,不会清除中断标志位。Thread.interrupted():静态方法,返回线程当前的中断标记状态同时清除中断标志位(置为false)。package com.morris.concurrent.lock.reentrantlock.trace;import java原创 2020-09-23 10:54:56 · 12978 阅读 · 0 评论 -
AQS源码分析之独占式获取锁和释放锁
AQS源码分析之独占式获取锁和释放锁队列同步器AbstractQueuedSynchronizer(以下简称AQS),是用来构建锁或者其他同步组件的基础框架,ReentrantLock、ReentrantReadWriteLock和CountDownLatch等并发工具类底层都是通过AQS实现的。AQS的数据结构同步状态AQS内部使用一个被volatile关键字修饰的state属性来表示同步状态,并提供了下面三个方法来对这个同步状态进行操作:private volatile int state;原创 2020-09-22 14:05:22 · 20682 阅读 · 0 评论 -
线程的中断与暴力停止
线程的中断stop()方法的线程不安全性Thread.stop()方法可以停止一个运行中的线程,但是这个方法已经被弃用了,这是为什么呢?先看下面一段代码:package com.morris.concurrent.thread.interrupt;import java.util.concurrent.TimeUnit;/** * 演示stop()方法带来的线程安全问题 */public class StopDemo { public static void main(Str原创 2020-09-21 14:04:59 · 20073 阅读 · 0 评论 -
多线程设计模式之保护性暂停模式
多线程设计模式之保护性暂停模式定义保护性暂停模式(Guarded Suspension Design Pattern):当线程在访问某个对象时,发现条件不满足时,就暂时挂起等待条件满足时再次访问。如果某个结果需要在多线程之间传递,则可以让这些线程关联到一个对象GuardedObject,但是如果这个结果需要不断的从一个线程到另一个线程那么可以使用消息队列(生产者/消费者)Thread.join()、Future就采用了保护性暂停模式。简单实现package com.morris.concurre原创 2020-09-14 14:56:30 · 36106 阅读 · 3 评论 -
synchronized批量重偏向与批量撤销
synchronized批量重偏向与批量撤销批量重偏向:如果一个类的大量对象被一个线程T1执行了同步操作,也就是大量对象先偏向了T1,T1同步结束后,另一个线程也将这些对象作为锁对象进行操作,会导偏向锁重偏向的操作。批量撤销:当一个偏向锁如果撤销次数到达40的时候就认为这个对象设计的有问题;那么JVM会把这个对象所对应的类所有的对象都撤销偏向锁;并且新实例化的对象也是不可偏向的。可以通过命令java -XX:+PrintFlagsFinal -version|grep 'BiasedLocking原创 2020-09-11 11:28:45 · 24393 阅读 · 2 评论 -
synchronized锁升级那点事
synchronized的升级过程引入JOL(Java Object Layout)来打印java对象头在内存中的字节码。<dependency> <groupId>org.openjdk.jol</groupId> <artifactId>jol-core</artifactId> <version>0.10</version></dependency>对象创建时对象创建时的状态有两种:原创 2020-09-09 14:50:05 · 12285 阅读 · 0 评论 -
java中对象在内存中的结构
对象的结构在JVM中,一般来说,Java对象都是分配在堆中,那么对象在堆中长什么样呢?对象头包含以下几个部分:MarkWord:包含对象的线程锁状态,另外还可以用来配合GC、存放该对象的hashCode、分代年龄等。Class Pointer:一个指向方法区中Class信息的指针,意味着该对象可随时知道自己是哪个Class的实例,默认开启压缩指针,占32位,关闭压缩,占64位。数组的长度:可选的,只有当对象是一个数组对象时才会有这个部分。对象的属性:占用内存空间取决于对象的属性数量和类型。原创 2020-09-02 17:25:09 · 16700 阅读 · 0 评论 -
探究Java多线程中线程的本质
线程的本质如果想要理解java中的线程,需要学习linux系统中线程的原语,然后自定义MyThread实现Thread的功能更加深入的理解。linux系统中线程的原语在linux中,创建一个线程的函数为pthread_create,其定义如下:int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);可以使用man pthread_cr原创 2020-09-01 15:17:31 · 12258 阅读 · 0 评论 -
ThreadLocal的内存泄漏与解决
ThreadLocal的内存泄漏内存泄漏:是指本应该被GC回收的无用对象没有被回收,导致内存空间的浪费,当内存泄露严重时会导致内存溢出。Java内存泄露的根本原因是:长生命周期的对象持有短生命周期对象的引用,尽管短生命周期对象已经不再需要,但是因为长生命周期对象持有它的引用而导致不能被GC回收。内存溢出:就是我们常说的OOM(OutOfMemoryError)异常,简单理解就是内存不够了,通常发生在程序申请的内存超出了JVM中可用内存的大小,就会抛出OOM异常。在JVM内存区域中,除了程序计数器外其他的原创 2020-07-22 15:06:13 · 28565 阅读 · 2 评论 -
ThreadLocal的使用与源码分析
ThreadLocal的使用与源码分析从名称看,ThreadLocal是Thread和Local的组合,也就是说每一个Thread都拥有自己独立的一个Local变量副本。ThreadLocal的简单使用package com.morris.jvm.threadlocal;import java.util.concurrent.TimeUnit;/** * 演示ThreadLocal的使用 */public class SimpleThreadLocalDemo { publi原创 2020-07-21 11:43:40 · 14682 阅读 · 0 评论