多线程高并发

进程:程序运行的基本单位 线程:cpu调度的基本单位,程序的不同执行路径

thread启动:继承thread类,实现runable接口,lamda表达式,线程池

thread sleep(进入timedwaiting状态) yield(线程到就绪状态,到等待队列里去)join(执行完方法后再继续执行,进入waiting状态,重启需要notify)等待进入同步代码块的锁(阻塞状态)

不建议使用stop,让正在等待的线程关闭一般使用interrupt,捕获异常

业务逻辑允许不加锁就不加锁,效率低一百倍,synchronized可重入锁,两个方法是同一把锁时不会出现死锁,父子类都有synchronized方法,锁的对象都是子类this,一个线程程序如果出现异常会释放掉锁,对象头的两位作标识:00 01 10 11

synchronized不能用String、常量、Integer、Long

执行时间短(加锁代码)线程少,用自旋锁,时间长,线程多,用系统锁

Atomic 实际上没有锁(自旋锁) LongAdder采用分段锁

lock要使用try catch finally不然如果出现异常别人永远拿不到锁

ReentrantLock()cas 手动加锁解锁 可以使用trylock尝试获得锁,使用lockInterruptibly(),可以对interrupt()方法作出响应,继续执行下面的代码,ReentrantLock(传参数true)公平锁,先来先执行,后来看队列排着 多个Condition实质上是多个等待队列

CountDownLatch await()计数减到零继续往下执行 CyclicBarrier(人数,runnable)await()人数够了就开始执行

MarriagePhaser 多个阶段

ReentrantReadWriteLock 读写锁 读 共享锁 写锁 排他锁,速写速度比互斥锁高,写的时候排他,读的时候可以一起进行

semaphore 限流,最多多少个线程同时运行,acquire方法获得某个许可,release方法释放掉 Exchanger 两个线程交换数据

Locksupport park()停止 unpark(t1)

Collections.synchronizedList(new LinkedList<>())能实现list的线程同步

volatile 修饰的引用变量,只是让引用可见,没有让引用指向的内容可见 notify()不释放锁 wait()让出锁

几乎所有的锁底层实现都是AQS:一个state状态以及一个双向链表,每个结点是线程

varhandle普通属性也可以进行原子性的操作,比反射更快,直接操作二进制码

ThreadLocal对象赋值只能被自己读取到,set到了当前线程的map里,不用务必remove掉,内存泄漏 用途:声明式事物,保证同一个

强引用:只要强引用消失,就会被自动回收

软引用:空间不够用的情况下才会被回收, 做缓存用

弱引用:只要垃圾回收,直接回收 一般用于容器 最常见的使用是ThreadLocal里的map的key弱引用指向ThreadLocal对象,若用强引用,就不会被回收,造成内存泄漏。

虚引用:给写JVM的人使用,new出来get不到值,被回收时存入队列通知被回收了,当直接内存指向堆外内存(操作系统分配的内存),就可以使用虚引用Queue检测对象回收时去释放堆外内存。

容器

Vector(一个一个)、hashtable(一对一对)加了所有方法都加synchronized,一般不用

concurrenthashmap读的效率高,并发放入的时候效率未必比hashtable和sychronizedhashmap效率高,但读取的时候快几十倍

多线程的时候考虑queue copyonwritearray读的时候不加锁,写的时候加锁

add poll(满了报异常,取出删除) offer peek(取出不删除) blockingqueue put take(阻塞)

queue和list的区别:queue有很多对线程友好的api,如上

Delayqueue按优先级调度(compareTo方法) sychronizedqueue不能往里面放东西,阻塞住等待其他线程往里面放东西,一般用于线程交互(放取一个对一个) 更强大的是Transferqueue(放取多个对多个)

线程池

ExecutorService的submit方法是异步的,方法里面传callable对象,返回值装在future类型里,future调用get方法阻塞

FutureTask既是callable,又是future,可以存放返回值,将task放进线程池或者线程中执行

CompletableFuture提供一堆任务的管理多个future的结果,allof,anyof 所有运行完成,任何一个运行完成继续运行

线程池维护着线程队列和任务队列,有七个参数:1.核心线程数2.最大线程数3.生存时间4.生存时间的单位5.任务队列6.线程工厂

7.当任务和线程满了的时候的拒绝策略:abort抛异常、discard扔掉,不抛异常、discardoldest扔掉排队时间最久的、callerRuns调用者处理任务,都很少用,一般自定义策略,如扔到kafka

Exeutors:线程池的工厂

1.SingleThreadExecutor 为什么有单线程的线程池:任务队列,生命周期管理

2.CachedThreadPool 线程数上线整数最大值,线程多了cpu切换消耗大量资源 场景:任务数忽高忽低

3.FixedThreadPool核心线程数和最大线程数一样,经验值 = cpu核数乘以期望cpu利用率乘以(1+等待时间/计算时间)场景任务数固定

4.ScheduledThreadPool定时任务线程池,用得少一半用quartz框架

并发是指任务提交,并行是指任务执行

源码分析:

​ Worker类:RunableAQS、需要AQS的原因是因为thread 任务

​ execute:核心线程不够加队列,队列满了加非核心线程

​ addWorker:count++ 数量+1 addworker 加任务 start 启动

5.WorkstealingPool 每个线程维护着自己的队列,偷任务过来执行 底层实现也是forkjionpool

6.ForkJionPool fork分叉 jion汇总

JMH

​ 线程测试报告,测开人员使用,开发人员安装JHM插件,test下注解使用

Disruptor

无锁,高并发,使用环形buffer,直接覆盖(不用清理)旧的数据,环形大小设置为2的n次方,取余转换成位运算,数组更快

开发步骤:

1.定义Event - 队列中需要处理的元素

2.定义Event工厂,用于填充队列

​ 这里牵扯到效率问题:disruptor在初始化的时候,会调用Event工厂,对ringBuffer进行内存的提前分配,之后只需要对里面的值进行更改即可,GC产生频率会降低

3.EventHandler

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值