本文涵盖了进程内多线程高并发常用技术。 进程内高并发 本文涵盖了进程内多线程高并发常用技术。简述启动线程的3种方式1:Thread2:Runnable3:Executors.newCacheThread sleep(自动复活到就绪状态)yield(让出一下cpu,返回到就绪状态)joinOS启动的线程数要大于java启动的线程(GC线程)状态:ready,running,new,terminated,waiting,blocked,timewaiting synchronizedhotspot使用对象头拿出两位记录锁升级特性有序性既可保证原子性,又可保证可见性可重入锁举例:父子类都为sychronized,锁的是子类对象,调用父类还是锁的子类出现异常锁会被释放 锁定目标synchronized(o)synchronized(this)synchronized(T.class) 同一个classloader空间把T.class加载到内存是单例的,不同classloader之间不能访问加了就不用加volatile锁升级偏向锁:对于第一个对象,刚开始只记录线程ID如果有线程争用,升级为自旋锁,默认自旋10次,之后升级为重量级锁,成为等待状态,不占CPU锁只能升级,不能降级执行时间短(加锁代码),线程数少,用自旋。执行时间长,线程数多,用系统锁 优化细化,由锁方法到锁变量避免对象的引用发生改变 volatile作用保证线程可见性MESI缓存一致性协议 禁止指令(二进制码)重排序a=new A();申请内存,初始化,赋值保证原子性并不能保证重排序读屏障或者写屏障可以防止指令重排序 不能保证原子性,要想保证原子性就用synchronized或者AtomicInteger CAS无锁,优化自旋类本身是原子性的,但是不能保证多个方法连续调用是原子性的CAS操作是CPU指令级别的支持ABA问题:1、加版本号;2、AtomicStampedReference如果基础类型无所谓;引用类型 Unsafe靠CPU的原语来实现并发特别高的情况:longadder(分段锁)->Atomic(无锁)->Sync(锁)分段锁也是cas操作 ReentrantLockfinally unlockReentrantLock尝试某些次可以对interrupt()方法做出响应true公平锁,可以指定不公平或者公平;sync只有不公平reen vs synccas vs sync锁升级trylockinterrupt()可以代替sync公平和非公平锁reen condition CountDownLatchawaitcountDown(原子性)与joinjoin必须要等到线程结束 barrierPhaser遗传算法barrier的升级版 readwritelock(读写锁)共享锁+排它锁stampedLock(升级态) semaphoreacquire、release令牌、限流 exchanger两两交换 LockSupport(JDK1.6)park unparkArrayList非线程安全notify不释放锁wait释放锁 conditionlock.newCondition生成一个等待队列生产者唤醒消费者,消费者唤醒生产者 AQS(CLH)核心是state,volatile intstate随着子类变化是一个双向链表线程队列向队列加东西用的是compareAndSetStatecompareAndSetTail 自旋 用CAS代替了锁定整条链表的操作varhandler指向某对象的引用compareAndSet int 为原子性操作1.通过handle普通属性也可以完成原子性操作2.比反射快直接操作二进制码 ThreadLocalset get不能获取到对象声明式实物,保证同一个connect 引用强new A(); 软System.gc属于fullGCSoftReference内存不够用先回收一次,在直接干掉,做缓存使用 弱只要垃圾回收就会回收ThreadLocal set() extend weakreference内存泄漏,漏了一块tl消失,ThreadLocal回收 务必要tl.remove 虚管理堆外内存,用来回收堆外内存PhantomReference垃圾回收看到就干掉,被干掉后收到一个通知(队列里添加一个值),队列里有值了就可以回收 堆外内存了Unsafe.allocMemory Unsafe.freeMomory 线程池callable和callable一样,只不过callable有返回值用来拿callable的执行结果future=service.submit异步操作future.get阻塞FutureTaskFutureTask->RunnableFuture->FutureCallable CompletableFuture一种任务的管理类ForkJoin 线程池(2种)ThreadPollExecutor(7个参数)池子用的是hashworkAddWorker外层自旋,数量+1;启动worker加锁 threadrunnable AQS 参数核心线程数coreThreadSize核心线程中的线程,即使时间到了,也会占着 最大线程数maxThreadSize生存时间liveTime生存时间单位TimeUtil任务队列ArrayBlokingQueueLinkedBlokingQueue(最大值是MAX_INTEGER) 线程工厂defaultThreadFactory拒绝策略线程池忙,任务队列满了,执行拒绝策略 ForkJoinPool大任务分解成小任务,在集合ForkJoinTaskRecursiveAction Executor(线程池的工厂)SingleLinkedBlockingQueue CachedSynchrousQueue fixedLinkedBlockingQueue sheduledDelayedWorkQueue newWorkStealingPoll每个线程都有自己的队列,自己的队列里面没有了去别的偷push pop不需要阻塞 但是poll需要底层用的是ForkJoinPoll很像mapReduce 定时任务Quartzcron Thread一般情况下线程数=CPU\*使用比\*(1+W/C)并发是任务提交,并行是任务执行,并行是并发的子集Linux线程调度方法:1、优先级;2、按时间片(默认);3、实时execute方法核心线程->队列->非核心线程 disruptor特点对比concurrentLinkedQueue实现JDK中没有concurrentArrayQueue只需要维护sequenece环形队列ringbuffer12%8=12&(8-1) eventeventFactory直接覆盖,不用清楚旧的数据,降低GC频率 eventHandlerProducerTypeProducerType.MULTIProducerType.SINGLE 等待策略(8种)BlockingWaitYieldingWaitSleepingWait JMHparrelStream.foreach->foreach 容器collectionlistcopyOnWriteArrayList写时复制 SynchronizedListArrayList线程不安全 LinkedList setqueue(针对高并发)queue与list相比添加了offer,peek,poll对线程友好的APIconcurrentLinkedQueueCASoffer添加,线程安全poll取并且remove,线程安全peek取不会remove,线程安全天生实现生产者,消费者模型 PriorityQueue用堆实现 DelayQueue阻塞按时间进行任务调度用PriorityQueue实现 ArrayQueueBlockingQueue(线程安全)LinkedBlockingQueueput,阻塞take,阻塞底层用LockSupport.park实现使用await,Condition->park ArrayBlockingQueuePriorityBlockingQueueSynchrousQueue容量为0两个线程直接交换数据,手对手 TransferQueueLinkedTransferQueue(等着人把资源取走才行,面对面付款,多人手对手) Mapvectorhashtable和vector自带锁,基本不用线程不安全 hashmaphashmapsynchronizedHashMap,加锁了 concurrentHashMap效率提高在读上面无序分段锁CAS将原本的一整个的Entry数组分成了若干段,分别将这若干段放在了不同的新的Segment数组中(分房间),每个Segment有各自的锁,以此提高效率 concurrentSkipListMap有序内部是SkipList(跳表)结构实现 简述 启动线程的3种方式 1:Thread 2:Runnable 3:Executors.newCacheThread sleep(自动复活到就绪状态) yield(让出一下cpu,返回到就绪状态) join OS启动的线程数要大于java启动的线程(GC线程) 状态:ready,running,new,terminated,waiting,blocked,timewaiting synchronized hotspot使用对象头拿出两位记录 锁升级 特性 有序性 既可保证原子性,又可保证可见性 可重入锁 举例:父子类都为sychronized,锁的是子类对象,调用父类还是锁的子类 出现异常锁会被释放 锁定目标 synchronized(o) synchronized(this) synchronized(T.class) 同一个classloader空间把T.class加载到内存是单例的,不同classloader之间不能访问 加了就不用加volatile 锁升级 偏向锁:对于第一个对象,刚开始只记录线程ID 如果有线程争用,升级为自旋锁,默认自旋10次,之后升级为重量级锁,成为等待状态,不占CPU 锁只能升级,不能降级 执行时间短(加锁代码),线程数少,用自旋。执行时间长,线程数多,用系统锁 优化 细化,由锁方法到锁变量 避免对象的引用发生改变 volatile 作用 保证线程可见性 MESI缓存一致性协议 禁止指令(二进制码)重排序 a=new A();申请内存,初始化,赋值 保证原子性并不能保证重排序 读屏障或者写屏障可以防止指令重排序 不能保证原子性,要想保证原子性就用synchronized或者AtomicInteger CAS 无锁,优化自旋 类本身是原子性的,但是不能保证多个方法连续调用是原子性的 CAS操作是CPU指令级别的支持 ABA问题:1、加版本号;2、AtomicStampedReference 如果基础类型无所谓;引用类型 Unsafe 靠CPU的原语来实现 并发特别高的情况:longadder(分段锁)->Atomic(无锁)->Sync(锁) 分段锁也是cas操作 ReentrantLock finally unlock ReentrantLock尝试某些次 可以对interrupt()方法做出响应 true公平锁,可以指定不公平或者公平;sync只有不公平 reen vs sync cas vs sync锁升级 trylock interrupt() 可以代替sync 公平和非公平锁 reen condition CountDownLatch await countDown(原子性) 与join join必须要等到线程结束 barrier Phaser 遗传算法 barrier的升级版 readwritelock(读写锁) 共享锁+排它锁 stampedLock(升级态) semaphore acquire、release 令牌、限流 exchanger 两两交换 LockSupport(JDK1.6) park unpark ArrayList非线程安全 notify不释放锁 wait释放锁 condition lock.newCondition生成一个等待队列 生产者唤醒消费者,消费者唤醒生产者 AQS(CLH) 核心是state,volatile int state随着子类变化 是一个双向链表线程队列 向队列加东西用的是compareAndSetState compareAndSetTail 自旋 用CAS代替了锁定整条链表的操作 varhandler 指向某对象的引用 compareAndSet int 为原子性操作 1.通过handle普通属性也可以完成原子性操作 2.比反射快直接操作二进制码 ThreadLocal set get不能获取到对象 声明式实物,保证同一个connect 引用 强 new A(); 软 System.gc属于fullGC SoftReference内存不够用先回收一次,在直接干掉,做缓存使用 弱 只要垃圾回收就会回收 ThreadLocal set() extend weakreference 内存泄漏,漏了一块 tl消失,ThreadLocal回收 务必要tl.remove 虚 管理堆外内存,用来回收堆外内存 PhantomReference 垃圾回收看到就干掉,被干掉后收到一个通知(队列里添加一个值),队列里有值了就可以回收 堆外内存了Unsafe.allocMemory Unsafe.freeMomory 线程池 callable 和callable一样,只不过callable有返回值 用来拿callable的执行结果 future=service.submit异步操作 future.get阻塞 FutureTask FutureTask->RunnableFuture->FutureCallable CompletableFuture 一种任务的管理类 ForkJoin 线程池(2种) ThreadPollExecutor(7个参数) 池子用的是hash work AddWorker 外层自旋,数量+1;启动worker加锁 thread runnable AQS 参数 核心线程数coreThreadSize 核心线程中的线程,即使时间到了,也会占着 最大线程数maxThreadSize 生存时间liveTime 生存时间单位TimeUtil 任务队列 ArrayBlokingQueue LinkedBlokingQueue(最大值是MAX_INTEGER) 线程工厂defaultThreadFactory 拒绝策略 线程池忙,任务队列满了,执行拒绝策略 ForkJoinPool 大任务分解成小任务,在集合 ForkJoinTask RecursiveAction Executor(线程池的工厂) Single LinkedBlockingQueue Cached SynchrousQueue fixed LinkedBlockingQueue sheduled DelayedWorkQueue newWorkStealingPoll 每个线程都有自己的队列,自己的队列里面没有了去别的偷 push pop不需要阻塞 但是poll需要 底层用的是ForkJoinPoll 很像mapReduce 定时任务 Quartz cron Thread 一般情况下线程数=CPU*使用比*(1+W/C) 并发是任务提交,并行是任务执行,并行是并发的子集 Linux线程调度方法:1、优先级;2、按时间片(默认);3、实时 execute方法 核心线程->队列->非核心线程 disruptor 特点 对比concurrentLinkedQueue实现 JDK中没有concurrentArrayQueue 只需要维护sequenece 环形队列ringbuffer 12%8=12&(8-1) event eventFactory 直接覆盖,不用清楚旧的数据,降低GC频率 eventHandler ProducerType ProducerType.MULTI ProducerType.SINGLE 等待策略(8种) BlockingWait YieldingWait SleepingWait JMH parrelStream.foreach->foreach 容器 collection list copyOnWriteArrayList 写时复制 SynchronizedList ArrayList 线程不安全 LinkedList set queue(针对高并发) queue与list相比 添加了offer,peek,poll对线程友好的API concurrentLinkedQueue CAS offer添加,线程安全 poll取并且remove,线程安全 peek取不会remove,线程安全 天生实现生产者,消费者模型 PriorityQueue 用堆实现 DelayQueue 阻塞 按时间进行任务调度 用PriorityQueue实现 ArrayQueue BlockingQueue(线程安全) LinkedBlockingQueue put,阻塞 take,阻塞 底层用LockSupport.park实现 使用await,Condition->park ArrayBlockingQueue PriorityBlockingQueue SynchrousQueue 容量为0 两个线程直接交换数据,手对手 TransferQueue LinkedTransferQueue(等着人把资源取走才行,面对面付款,多人手对手) Map vector hashtable和vector自带锁,基本不用 线程不安全 hashmap hashmap synchronizedHashMap,加锁了 concurrentHashMap 效率提高在读上面 无序 分段锁 CAS 将原本的一整个的Entry数组分成了若干段,分别将这若干段放在了不同的新的Segment数组中(分房间),每个Segment有各自的锁,以此提高效率 concurrentSkipListMap 有序 内部是SkipList(跳表)结构实现