前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >JUC容器介绍

JUC容器介绍

作者头像
Java技术债务
发布2022-08-09 13:12:58
3070
发布2022-08-09 13:12:58
举报
文章被收录于专栏:Java技术债务

目录

JUC结构

  1. tools(工具类):又叫信号量三组工具类,包含有
    1. CountDownLatch(倒计数) 是一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待
    2. CyclicBarrier(循环栅栏) 之所以叫barrier,是因为是一个同步辅助类,允许一组线程互相等待,直到到达某个公共屏障点 ,并且在释放等待线程后可以重用。
    3. Semaphore(信号量) 是一个计数信号量,它的本质是一个“共享锁“。信号量维护了一个信号量许可集。线程可以通过调用 acquire()来获取信号量的许可;当信号量中有可用的许可时,线程能获取该许可;否则线程必须等待,直到有可用的许可为止。 线程可以通过release()来释放它所持有的信号量许可。
  2. executor(执行者):是Java里面线程池的顶级接口,但它只是一个执行线程的工具,真正的线程池接口是ExecutorService,里面包含的类有:
    1. ScheduledExecutorService 解决那些需要任务重复执行的问题
    2. ScheduledThreadPoolExecutor 周期性任务调度的类实现
  3. atomic(原子性包):是JDK提供的一组原子操作类,
  4. locks(锁包):是JDK提供的锁机制,相比synchronized关键字来进行同步锁,功能更加强大,它为锁提供了一个框架,该框架允许更灵活地使用锁包含的实现类有:
    1. ReentrantLock 它是独占锁,是指只能被独自占领,即同一个时间点只能被一个线程锁获取到的锁。
    2. ReentrantReadWriteLock 它包括子类ReadLock和WriteLock。ReadLock是共享锁,而WriteLock是独占锁。
    3. LockSupport 它具备阻塞线程和解除阻塞线程的功能,并且不会引发死锁
  5. collections(集合类):主要是提供线程安全的集合, 比如:
    1. ArrayList对应的高并发类是CopyOnWriteArrayList,
    2. HashSet对应的高并发类是 CopyOnWriteArraySet,
    3. HashMap对应的高并发类是ConcurrentHashMap等等

1、tools(工具类)

JUC 中的同步器三个主要的成员:CountDownLatch、CyclicBarrier 和 Semaphore,通过它们可以方便地实现很多线程之间协作的功能。

CountDownLatch

叫倒计数,允许一个或多个线程等待某些操作完成。

看几个场景:1、跑步比赛,裁判需要等到所有的运动员(“其他线程”)都跑到终点(达到目标),才能去算排名和颁奖。

2、模拟并发,我需要启动 100 个线程去同时访问某一个地址,我希望它们能同时并发,而不是一个一个的去执行。

用法:CountDownLatch 构造方法指明计数数量,被等待线程调用 countDown 将计数器减 1,等待线程使用 await 进行线程等待。

CyclicBarrier

叫循环栅栏,它实现让一组线程等待至某个状态之后再全部同时执行,而且当所有等待线程被释放后,CyclicBarrier 可以被重复使用。CyclicBarrier 的典型应用场景是用来等待并发线程结束。

CyclicBarrier 的主要方法是 await(),await() 每被调用一次,计数便会减少 1,并阻塞住当前线程。当计数减至 0 时,阻塞解除,所有在此 CyclicBarrier 上面阻塞的线程开始运行。在这之后,如果再次调用 await(),计数就又会变成 N-1,新一轮重新开始,这便是 Cyclic 的含义所在。CyclicBarrier.await() 带有返回值,用来表示当前线程是第几个到达这个 Barrier 的线程。

Semaphore

Java 版本的信号量实现,用于控制同时访问的线程个数,来达到限制通用资源访问的目的,其原理是通过 acquire() 获取一个许可,如果没有就等待,而 release() 释放一个许可。

如果 Semaphore 的数值被初始化为 1,那么一个线程就可以通过 acquire 进入互斥状态,本质上和互斥锁是非常相似的。

但是区别也非常明显,比如互斥锁是有持有者的,而对于 Semaphore 这种计数器结构,虽然有类似功能,但其实不存在真正意义的持有者,除非我们进行扩展包装。

CyclicBarrier 和 CountDownLatch 区别

CountDownLatch 是不可以重置的,所以无法重用,CyclicBarrier 没有这种限制,可以重用。

CountDownLatch 的基本操作组合是 countDown/await,调用 await 的线程阻塞等待 countDown 足够的次数,不管你是在一个线程还是多个线程里 countDown,只要次数足够即可。CyclicBarrier 的基本操作组合就是 await,当所有的伙伴都调用了 await,才会继续进行任务,并自动进行重置。

CountDownLatch 目的是让一个线程等待其他 N 个线程达到某个条件后,自己再去做某个事(通过 CyclicBarrier 的第二个构造方法 public CyclicBarrier(int parties, Runnable barrierAction),在新线程里做事可以达到同样的效果)。

而 CyclicBarrier 的目的是让 N 多线程互相等待直到所有的都达到某个状态,然后这 N 个线程再继续执行各自后续(通过 CountDownLatch 在某些场合也能完成类似的效果)。

2、executor

关于线程池更多更详细的请看之前的文章:

Java创建线程池的方式

线程池的理解以及使用

3、atomic

包含有AtomicBoolean、AtomicInteger、AtomicIntegerArray等原子变量类,他们的实现原理大多是持有它们各自的对应的类型变量value,而且被volatile关键字修饰了。这样来保证每次一个线程要使用它都会拿到最新的值。

4、Lock锁(重点)

什么是Synchronized?

Synchronized和lock

  1. Lock是一个接口,而synchronized是关键字。
  2. synchronized会自动释放锁,而Lock必须手动释放锁。
  3. Lock可以让等待锁的线程响应中断,而synchronized不会,线程会一直等待下去。
  4. 通过Lock可以知道线程有没有拿到锁,而synchronized不能。
  5. Lock能提高多个线程读操作的效率。
  6. synchronized能锁住类、方法和代码块,而Lock是块范围内的

synchronized是Java的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码。JDK1.5以后引入了自旋锁、锁粗化、轻量级锁,偏向锁来有优化关键字的性能。

Lock是一个接口,而synchronized是Java中的关键字,synchronized是内置的语言实现;synchronized在发生异常时,会自动释放线程占有的锁,因此不会导致死锁现象发生;而Lock在发生异常时,如果没有主动通过unLock()去释放锁,则很可能造成死锁现象,因此使用Lock时需要在finally块中释放锁;Lock可以让等待锁的线程响应中断,而synchronized却不行,使用synchronized时,等待的线程会一直等待下去,不能够响应中断;通过Lock可以知道有没有成功获取锁,而synchronized却无法办到。

Syncronized锁,如果用这个关键字修饰一个静态方法,锁住了什么?如果修饰成员方法,锁住了什么?

synchronized修饰静态方法以及同步代码块的synchronized (类.class)用法锁的是类,线程想要执行对应同步代码,需要获得类锁。

synchronized修饰成员方法,线程获取的是当前调用该方法的对象实例的对象锁。

对象锁:

它只作用于同一个对象,如果调用两个同一个类的对象上的同步代码块,就不会进行同步。

类锁:

锁住的是当前类的 Class 对象,它会作用于整个类,也就是说两个线程调用同一个类的不同对象上的这种同步语句,也会进行同步。

1、有线程访问对象的同步代码块时,其他线程是可以访问该对象的非同步代码块的。

2、若锁住的是同一个对象,一个线程在访问对象的同步代码块(同步方法)时,另一个访问对象的同步代码块(同步方法)的线程会被阻塞。

3、若锁住的是同一个对象,一个线程在访问对象的同步代码块时,另一个访问对象同步方法的线程会被阻塞,反之亦然(这点在后续介绍 synchronized 底层原理之后你就会明白原因了)。

4、同一个类的不同对象的对象锁互不干扰

5、类锁作用于整个类

更多锁(ReentrantLock、ReadWriteLock读写锁)的文章请关注更多文章

5、集合类不安全

ArrayList、HashSet、HashMap线程都不安全

在集合中 Vector 和 HashTable 是线程安全的。源码中把各自核心方法添加上了synchronized 关键字。

Collections 工具类提供了相关的 API,可以让上面那 3 个不安全的集合变为安全的。

  1. Collections.synchronizedCollection(c)
  2. Collections.synchronizedList(list)
  3. Collections.synchronizedMap(m)
  4. Collections.synchronizedSet(s)
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-03-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • JUC结构
  • 1、tools(工具类)
    • CountDownLatch
      • CyclicBarrier
        • Semaphore
          • CyclicBarrier 和 CountDownLatch 区别
          • 2、executor
            • Java创建线程池的方式
              • 线程池的理解以及使用
              • 3、atomic
              • 4、Lock锁(重点)
                • 什么是Synchronized?
                  • Synchronized和lock
                  • 5、集合类不安全
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档