Java多线程-并发设计模式

2019-11-19  本文已影响0人  xgangzai

为了解决多线程带来的并发问题,业界总结出的一套设计模式,类似缓存更新设计模式、23种设计模式一样

并发编程领域的问题总结为3个:分工、同步和互斥。同步和互斥相关问题更多源自于微观,分工问题则是源自于宏观。我们在解决问题的时候先从宏观设计,而后再进行微观设计。

一、不可变模式 Immutability

见String Integer,自己实现不可变类需要注意的点

  1. 类定义成final(不允许被继承)
  2. 所有属性设置成final,只提供get操作
  3. 如果属性也是对象,则该对象也应该是不可变的
  4. 构造时“逸出”?在构造器中将this赋值给全局变量,
二、Copy-on-Write模式

改模式也是不可变模式的一种实现手段,比如string中的replace,实际上返回的是一个新的string对象

CopyOnWriteArrayListCopyOnWriteArraySet ,写时复制思想就是在写的时候,赋值一份数据,写完后再赋值给原来的引用。这样能做到读时不加锁,但是新数据不会被立即读到。需要业务承受一定的时间的不一致的。

适用的场景:读多写少

三、线程本地存储模式

将共享资源进行线程封闭

四、GuardedSuspension模式

保护性暂停,等待唤醒机制的规范实现,典型场景:生产者消费者模型。

多线程版本的if

五、Balking模式

Balking模式本质上是一种规范化地解决“多线程版本的if”的方案 ,

实现方案:

Balking模式和Guarded Suspension模式从实现上看似乎没有多大的关系,Balking模式只需要用互斥锁就能 解决,而Guarded Suspension模式则要用到管程这种高级的并发原语;但是从应用的角度来看,它们解决 的都是“线程安全的if”语义,不同之处在于,Guarded Suspension模式会等待if条件为真,而Balking模式 不会等待。

Balking模式的典型应用场景:并发初始化资源,只要初始化一次。

六、Thread-Per-Message模式

为每个任务分配一个独立的线程,最经典的应用场景是网络编程里服务端的实现(线程池只是这个模式的实现上的优化)

但是在Java语言中,线程是一个重对象,主要是其创建和销毁过程重(至于为什么重,后续再研究)。所以在实现上有两种优化方案

  1. 采用线程池,避免线程频繁的创建和销毁
  2. 采用更轻量级的线程,在其他语言中叫协程,Java中对其支持的方案是Fiber
七、WorkerThread模式

Thread-Per-Message的改进版,线程池

八、两阶段终止模式

如何优雅地停止线程,在Java中,提供了stop()方法,这个方式会直接终止线程,不给任何执行收尾工作的机会,所以逐渐被过时了,为了能够优雅地停止线程(给线程执行收尾工作),采用两阶段终止模式,第一阶段,向目标线程发送终止指令,第二阶段目标线程响应终止指令。Thread#interrupt().

九、生产者消费者模式

核心方案用队列存储任务,生产者和消费者之间不直接强依赖,解耦。

线程池本身就是生产者消费者模式的实现,

上一篇下一篇

猜你喜欢

热点阅读