Java编程学习必备:最强并发编程学习大纲,简洁,但不失重点!

一、多线程

1. 无返回值

①. 实现runnable接口

  • run方法不会抛异常
  • 需要Thread的start方法启动多线程

②. 继承Thread类

  • java只能单继承,所以扩展收到限制

2. 有返回值(实现Callable接口)

①. future拿 到返回值

  • 拿返回值
  • 判断任务是否执行完
  • 中断任务
  • 向线程池summit的多个任务,只有全部执行完,future才可以get到值

②. call方法会抛异常

③. 需要Thread的start方法启动多线程

3. 解决future的get方法阻塞问题completionService

①. take方法也是阻塞方法,只是会拿其中一个完成的future

②. poll方法和take类似,只是poll方法不会阻塞,没有完成的任务直接返回null,可以加等待的时间

4. ThreadLocal

①. 线程间的数据隔离

②. 解决多线程安全问题

  • set(往里面放数据
  • get(从里面取当前线程的数据
  • 使用完get和set后要用remove去除内部map的key与value的引用关系,因为key是弱引用,下次gc的时候被回收,导致value会被线程长期持有,造成内存泄露

③. 优雅做法:帮ThreadLocal包装到单例中

二、并发包

  • BlockingQueue
  • ConcurrentHashMap
  • ReentrantLock
  • LockSupport
  • CyclicBarrier
  • CountDownL atch
  • ReadWriteLock
  • Semaphore
  • Condition

三、相关问题理解

1. 对volatile的理解

①. 虚拟机提供的轻量的同步机制

  • 保证可见性:前后加了内存屏障
  • 不保证原子性
  • 禁止指令重排:当程序执行到volatile变量的读操作或者写操作时,在其前面的操作的更改肯定全部已经进行,且结果已经对后面的操作可见;在其后面的操作肯定还没有进行

②. 在JMM的理解

  • 可见性:主内存,线程工作内存
  • 原子性
  • 有序性质:指令重排

③. 哪些地方用过volatile

  • 单例模式的double check (禁止 了指令重排)
    • 在真正的new操作对象的时候,new命令其实包含了,开辟内存,初始化内存等操作:
    • 多线程情况下,一个线程在new的时候,内存还没有被初始化完全,另一个线程进来后发现对象引用已经不是null了,就会返回一个未初始化完全的对象,从而造成出错
  • 代理模式

2. CAS的理解(比较交换)

①. 工作内存与主存数据比较一样的时候修改,不一样的时候重复读取主存,跟新工作内存数据

②. CAS底层,unsafe的理解:native方法,unsafe类

③. CAS缺点:

A. 循环时间长,CPU开销大

B.只能保证一个共享变量的原子性:不能保证代码块的原子性

C. 有ABA问题:

  • 原因:一个线程短时间内把变量由A改成B,再由B改成A
  • 解决:加入时间戳版本,原子引用
  • AtomicStampedReference

3. Arayit是线程不安全的,解决线程不安全的方言

  • 加锁
  • 使用vector线程安全的数组
  • 使用Collections内部方法转为线程安全的List

4. 各种锁的理解

①. 公平锁/非公平锁

  • 是什么:公平锁只等待锁的线程按先来先得顺序得到锁
  • 两者区别:公平锁按FIFO的等待队列等待锁, 锁操作耗时
  • ReentrantLock默认是非公平锁,synchronize是非公平锁

②. 对象锁

  • Synchronize.每 个对象的头部markword字段有标志标志,monitorenter 和monitorexit 指令来实现同步的,monitor管程 来控制
  • 头部mark word字段,有锁状态,是否偏向锁,锁标志
  • JVM级的不需要业务代码控制

③. 偏向锁

  • 偏向锁的核心思想是,如果一个线程获得 了锁,那么锁就进入偏向模式,此时Mark Word的结构也变为偏向锁结构,当这个线程再次请求锁时,无需再做任何同步操作,即获取锁的过程,这样就省去了大量有关锁申请的操作

④. 可重入锁

  • 是什么:同一个线程外层函数获取锁后,内存递归函数仍然能获得锁
  • ReentrantLock和Snychronize是典型的可重入锁
  • 底层实现原理,ReentrantLock是AQS同步队列, Snychronize是锁住的对象头部字段记录的标志,在monitor中 会做计数

⑤. 自旋锁

  • SpinLock,短时间的自旋,不会释放CPU

⑥. 独占锁(写)/共享锁(读)

  • ReentrantReadWriteLock

⑦. 读写锁

  • 写的时候排他,读的时候共享排他写锁

⑧. 锁优化

  • 偏向税→轻量级锁→自旋锁→重量级锁

5. CountDownLatch/CyclicBarrier/Semaphore

①. CountDownLatch

  • 让一些线程阻塞,知道一些线程完成操作
  • 一些线程执行await(阻塞,一些线程完成操作后执行CountDownQ减数
  • 案例:等待人到齐,才开会

②. CyclicBarrier

  • 一些线程阻塞在一个点, 然后同时进行
  • await(方法阻塞
  • 案例:跑步比赛到齐开始

③. Semaphore

  • 用于并大资源数量的控制,同-时间只能有固定数的线程进入临界区
  • 案例:抢车位

6. 阻塞队列

①. 是什么

  • 阻塞队列空的时候,从队列获取数据的线程会被阻塞
  • 阻塞队列满的时候,往队列放数据的线程会被阻塞

②. 好处

  • 不需要关心什么时候阻塞线程,什么时候唤醒,阻塞队列帮处理了

③. Blockqueue核心方法处理出错

  • 抛异常
  • 返回特殊值
  • 一直阻塞
  • 超时退出

④. 架构种类

  • ArrayBlockingQueue基于数组的有界
  • LinkedBlockingDeque基于链表的有界,默认界值很大
  • SynchronousQueue同步队列,不存数据,生产一个消费一 个
  • PriorityBlockingQueue有优先级的无界阻塞队列
  • delayQueue延迟无界阻塞队列
  • LinkedTransferQueue链表结构的无界阻塞队列
  • LinkedBlockingDeque链表结构阻塞双端队列

⑤. 用在哪里

  • 生产者消费者模式
  • 线程池
  • 消息中间件

7. Java线程池,ThreadPoolExecutor的理解 田

①. 线程池优势

  • 充分利用CPU
  • 减少频繁创建线程的性能消耗

②. 线程池的使用

  • 自定义线程池,继承ThreadPoolExecutor
  • 线程池函数
    • Executors.newCachedThreadPool
    • Executors.newSingle ThreadPool
    • Executors.newFixedThreadPool
    • Executors.newScheduleThreadPool

③. 线程池的重要参数

  • corePoolSize线程池的常驻核心线程数
  • maximumpoolSize线程池能够容纳的最多线程数
  • keepAliveTime多余核心线程数的空闲线程的最多存活时间
  • unit keepAlive Time的单位
  • workqueue任务队列,提交到线程池还未处理的任务
  • threadFactory线程池中线程的工厂。用于创建线程,
  • handler拒绝策略,任务丢列满,线程数达到最大时,做的处理

④. 线程池的工作原理

a. 创建线程池后等待提交任务

b. 调用execute添加任务,线程池做的判断:

  • 如果线程数量小于核心线程数,就马上创建线程处理任务
  • 如果正在运行的线程数大于核心线程数,就将任务放入任务队列
  • 如果任务队列满了,且正在运行的线程数小于最大线程数,就创建非核心线程处理任务
  • 如果队列满了,且线程数达到最大线程数,线程池使用饱和拒绝策略处理任务

c. 当一个线程任务处理完,会从任务队列中取下一个任务执行

d. 当一个线程空闲时间超过keepAliveTime时候,线程池处理(如果当前线程数量大于核心线程数,那么这个线程就会被销毁)

8. 线程池参数的合理配置

①. 线程池拒绝策略

  • AbortPoliy直接抛出异ReiectedException.阻止系统运行
  • CallerRunPoliy由提交任务的业务线程处理_
  • DisadndeltPole她弃队列中等待最久的任务,然后把最新的任务加入人任务队列
  • DicardPolil 直接丢弃任务,不予处理。也不抛出异常,允许任务丢弃

②. 创建线程池的方法

a. 使用自定义线程池

b. executors线程池问题:

  • 默认使用链表有界阻塞队列,界很大,导致内存溢出
  • 缓存调度线程池会创建大量线程导致资源占用大

③. 如何合理配置线程池数量

  • CPU密集型操作: cpu核心数+1
  • IO密集型操作: 2xcpu核心数

9. 死锁定位分析

①. 产生原因:

  • 系统资源不足
  • 资源分配不当
  • 线程执行顺序不合适
  • 线程互斥,资源持有等待,不可剥夺

②. 解决:jps定位到进程id, jstack定位到栈代码

# 链接 Java程序员福利"常用资料分享"

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343

推荐阅读更多精彩内容