JAVA和Nginx 教程大全

网站首页 > 精选教程 正文

Java面试必考问题:一篇文章理清Java并发包JUC

wys521 2024-11-06 20:35:15 精选教程 26 ℃ 0 评论

Java并发包 JUC 是 在Java 5.0添加的 java.util.concurrent 包的简称,目的就是为了更好地支持高并发任务,让开发者进行多线程编程时可以有效地减少竞争条件和死锁线程。JUC一直也是Java面试中常考的内容,本文将JUC包的内容梳理一下。

JUC包的组成

JUC包主要包括5个部分:工具类(tools)、线程池类(Executor)、原子操作类(Atomic)、锁类(Locks)、并发容器类(Collections)。

工具类

工具类主要包括:闭锁(CountDownLatch)、栅栏(CyclicBarrier)和信号量(Semaphone)、线程池工厂类(Executors)、交换器(Exchanger)。

(1)CountDownLatch 是一个同步辅助类,CountDown的意思是倒计数,Latch的意思是门闩(shuan一声)。这个工具用来控制线程等待,让某一个线程等待直到倒计数结束再开始执行。常用在线程需要等待一组操作完成之后才能执行的场景中。

(2)CyclicBarrier 也是线程并发控制工具,Barrier的意思是栅(zha四声)栏,作用是阻止线程继续执行,要求线程在栅栏外等待。CyclicBarrier 让一组线程互相等待,直到所有线程都到达某个公共屏障点 ,才继续执行。

(3)Semaphore 是一个计数信号量,它的本质是一个“共享锁“。信号量维护了一个信号量许可集。线程可以通过调用 acquire()来获取信号量的许可;当信号量中有可用的许可时,线程能获取该许可;否则线程必须等待,直到有可用的许可为止。 线程可以通过release()来释放它所持有的信号量许可。

(4)Executors 主要是用来创建线程池。

阿里巴巴Java开发手册中明确指出:不允许使用Executors去创建,而是通过ThreadPoolExecutor的方式,这样的处理方式是让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。

(5)Exchanger 用于两个线程交换对象,一个线程负责生产对象,另一个线程负责消费对象。实际当中用得比较少。


线程池类

Java1.5引入的Executor框架实现的是线程池的功能,实现了工作单元(任务)和任务执行分离。Executor框架主要包括3大部分:

(1)任务,即工作单元。执行任务需要实现的接口是 Runnable 接口(无返回值)或者 Callable 接口(有返回值);

(2)任务的执行。把任务分派给多个线程的执行机制,包括 Executor 接口及继承自 Executor 接口的 ExecutorService 接口。

(3)异步任务。包括 Future 接口及实现了 Future 接口的 FutureTask 类。

Executor 是线程池的顶级接口,但它只有一个执行线程的方法 execute(),主要的线程池接口是 ExecutorService

ExecutorService接口的实现类有两个:

(1)ThreadPoolExecutor 是线程池的具体实现,用来执行被提交的任务,包括Runnable任务或者 Callable 任务。

(2)ScheduledThreadPoolExecutor 继承了 ThreadPoolExecutor 并实现了 ScheduledExecutorService 接口。主要用于在给定的延迟后执行任务或者定期执行任务。

关于线程池类ThreadPoolExecutor 可以参考前文《Java面试必考问题:Tomcat为啥不用Java原生线程池 》。


原子操作类

JDK提供的一组原子操作类,实现原理大多是内部持有类型变量value,而且变量被volatile关键字修饰。这样保证每次线程使用变量的时候,都会拿到最新的值。

当多个线程同时对原子类型变量的值进行更新时,仅有一个线程能成功,而未成功的线程可以像自旋锁一样,继续尝试,一直等到执行成功。

java.util.concurrent.atomic 包中共有12个类:

  • 原子类型:AtomicBoolean,AtomicInteger,AtomicLong,AtomicReference
  • 原子数组类型:AtomicIntegerArray,AtomicLongArray,AtomicReferenceArray
  • 原子属性更新器:AtomicLongFieldUpdater,AtomicIntegerFieldUpdater,AtomicReferenceFieldUpdater
  • 解决 ABA 问题的原子类型:AtomicMarkableReference,AtomicStampedReference

关于ABA问题的介绍,可以参考前文《Java面试必考问题:如何解决CAS算法的ABA问题 》。


锁类

Locks 包(java.util.concurrent.locks)是JDK提供的锁机制,相比 synchronized 关键字,Locks包提供的框架功能更加强大,允许开发者更灵活地使用锁。

主要的实现类包括:

(1)可重入锁 ReentrantLock:ReentrantLock是独占锁,是指只能被独自占领,即同一个时间点只能被一个线程锁获取到的锁。

(2)可重入读写锁 ReentrantReadWriteLock:它包括两个内部类 ReadLock WriteLock 。ReadLock是共享锁,而WriteLock是独占锁。

(3)线程阻塞工具类 LockSupport:具备阻塞线程和解除阻塞线程的功能,并且不会引发死锁。

关于可重入锁的介绍,可参考前文《Java编程必考问题:什么是ReentrantLock? 》。


并发容器类

主要是提供线程安全的容器。大部分常用的Java集合类(Set、List和Map)都不是线程安全的,不过一般都有对应的线程安全的并发容器类,比如:

(1)ArrayList 对应的并发容器类是 CopyOnWriteArrayList

(2)HashSet 对应的并发容器类是 CopyOnWriteArraySet

(3)HashMap 对应的并发容器类是 ConcurrentHashMap

我会持续更新关于物联网、云原生以及数字科技方面的文章,用简单的语言描述复杂的技术,也会偶尔发表一下对IT产业的看法,欢迎大家关注,谢谢。

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表