文章目录
- Java并发工具类:这些知识点你不可不知!
- 一、Executor框架:线程管理的艺术
- 1.1 线程池的基本概念
- 1.2 线程池的类型
- FixedThreadPool
- CachedThreadPool
- SingleThreadExecutor
- ScheduledThreadPool
- 二、CountDownLatch:让线程等待
- 2.1 CountDownLatch的基本用法
- 2.2 CountDownLatch的注意事项
- 三、CyclicBarrier:循环等待的屏障
- 3.1 CyclicBarrier的基本用法
- 3.2 CyclicBarrier的注意事项
- 四、Semaphore:控制并发访问
- 4.1 Semaphore的基本用法
- 4.2 Semaphore的注意事项
- 总结
- 📚 领取 | 1000+ 套高质量面试题大合集(无套路,闫工带你飞一把)!
Java并发工具类:这些知识点你不可不知!
大家好,我是闫工,今天咱们来聊一聊Java中的并发工具类。作为一名Java工程师,如果你对并发编程还不是很熟悉的话,那这篇文章可能会让你眼前一亮!并发工具类是Java中非常重要的知识点,掌握它们不仅能让你在面试中脱颖而出,还能在实际开发中写出高效、优雅的代码。
那么,什么是并发工具类呢?简单来说,就是Java提供的一些帮助我们处理多线程并发问题的类。这些类分布在java.util.concurrent包下,包含了诸如线程池、锁、同步器等等工具。今天咱们就来逐一了解一下这些工具类,看看它们各自有什么特点和应用场景。
一、Executor框架:线程管理的艺术
1.1 线程池的基本概念
在Java中,Executor框架是并发编程的核心,它简化了线程的管理和使用。传统的线程创建方式是通过new Thread()来启动一个线程,但这种方式存在一些问题:
- 资源浪费:每次创建线程都需要消耗一定的系统资源。
- 难以管理:当线程数量很多时,很难统一管理和控制它们。
而Executor框架则很好地解决了这些问题。它采用“线程池”的概念,允许我们将任务提交到一个线程池中,由线程池来管理和复用线程,从而提高程序的性能和资源利用率。
1.2 线程池的类型
Java中的线程池主要有以下几种实现:
- FixedThreadPool:固定大小的线程池。
- CachedThreadPool:可缓存的线程池,适用于执行短期任务。
- SingleThreadExecutor:单线程的线程池,保证所有任务串行执行。
- ScheduledThreadPool:支持延迟和周期性任务的线程池。
FixedThreadPool
FixedThreadPool是最常见的线程池类型之一。它会维护一个固定大小的线程池,当提交的任务数量超过线程池容量时,剩下的任务会被放入队列中等待执行。
ExecutorServiceexecutor=Executors.newFixedThreadPool(5);for(inti=0;i<10;i++){executor.submit(()->System.out.println("Task executed by "+Thread.currentThread().getName()));}executor.shutdown();特点:
- 线程池大小固定。
- 适用于任务数量较多且需要控制资源消耗的场景。
CachedThreadPool
CachedThreadPool是一个动态扩展的线程池。当提交的任务数量超过当前线程数时,它会创建新的线程来执行这些任务;而当线程空闲一段时间后,它们会被回收。
ExecutorServiceexecutor=Executors.newCachedThreadPool();for(inti=0;i<10;i++){executor.submit(()->System.out.println("Task executed by "+Thread.currentThread().getName()));}executor.shutdown();特点:
- 线程池大小动态调整。
- 适用于短期、临时的任务。
SingleThreadExecutor
SingleThreadExecutor是一个单线程的线程池,所有任务都会串行执行。虽然看起来效率不高,但在某些场景下非常有用。
ExecutorServiceexecutor=Executors.newSingleThreadExecutor();for(inti=0;i<5;i++){executor.submit(()->System.out.println("Task "+i+" executed by "+Thread.currentThread().getName()));}executor.shutdown();特点:
- 所有任务串行执行。
- 适用于需要保证顺序执行的场景。
ScheduledThreadPool
ScheduledThreadPool支持延迟和周期性任务的执行。它结合了固定大小线程池的功能,并提供了schedule()方法来安排任务。
ScheduledExecutorServiceexecutor=Executors.newScheduledThreadPool(3);// 延迟1秒后执行executor.schedule(()->System.out.println("Delayed task executed"),1,TimeUnit.SECONDS);// 每隔2秒执行一次,第一次延迟5秒executor.scheduleAtFixedRate(()->System.out.println("Periodic task executed"),5,2,TimeUnit.SECONDS);特点:
- 支持延迟和周期性任务。
- 线程池大小固定。
二、CountDownLatch:让线程等待
在并发编程中,我们常常需要让一个或多个线程等待某些条件满足后才能继续执行。CountDownLatch就是一个非常有用的工具类,它允许我们在指定的“门”关闭之前阻塞线程。
2.1 CountDownLatch的基本用法
CountDownLatch通过计数器来实现同步。初始化时需要指定一个计数值,每次调用countDown()方法会将计数值减1,当计数值为0时,“门”才会打开,被阻塞的线程才能继续执行。
importjava.util.concurrent.CountDownLatch;publicclassCountDownLatchExample{publicstaticvoidmain(String[]args)throwsInterruptedException{CountDownLatchlatch=newCountDownLatch(3);// 启动三个子线程,分别完成任务后调用countDown()for(inti=0;i<3;i++){newThread(()->{System.out.println("Task completed by "+Thread.currentThread().getName());latch.countDown();}).start();}// 主线程等待latch完成latch.await();System.out.println("All tasks are done!");}}运行结果:
Task completed by Thread-0 Task completed by Thread-1 Task completed by Thread-2 All tasks are done!2.2 CountDownLatch的注意事项
- 不可重用:一旦计数值减为0,
CountDownLatch就不能再使用了。 - 线程安全:多个线程同时调用
countDown()方法是线程安全的。
三、CyclicBarrier:循环等待的屏障
如果说CountDownLatch是一个“门”,那么CyclicBarrier就是一个可以重复使用的“门”。它允许多个线程在某个指定的点上互相等待,直到所有线程都到达该点后才继续执行。
3.1 CyclicBarrier的基本用法
CyclicBarrier通过一个同步点来协调多个线程。初始化时需要指定参与同步的线程数量,并且可以通过重置方法reset()重新使用它。
importjava.util.concurrent.CyclicBarrier;publicclassCyclicBarrierExample{publicstaticvoidmain(String[]args)throwsInterruptedException{CyclicBarrierbarrier=newCyclicBarrier(3,()->System.out.println("All threads are at the barrier!"));for(inti=0;i<3;i++){newThread(()->{System.out.println(Thread.currentThread().getName()+" is waiting at the barrier.");try{barrier.await();}catch(InterruptedExceptione){Thread.currentThread().interrupt();}System.out.println(Thread.currentThread().getName()+" continues execution.");}).start();}}}运行结果:
Thread-0 is waiting at the barrier. Thread-1 is waiting at the barrier. Thread-2 is waiting at the barrier. All threads are at the barrier! Thread-0 continues execution. Thread-1 continues execution. Thread-2 continues execution.3.2 CyclicBarrier的注意事项
- 可重用:
CyclicBarrier可以通过调用reset()方法重新使用。 - 线程安全:多个线程同时调用
await()方法是线程安全的。
四、Semaphore:控制并发访问
在某些场景下,我们可能需要限制同时访问某个资源的线程数量。Semaphore就是用来实现这种功能的工具类。
4.1 Semaphore的基本用法
Semaphore通过许可来控制并发访问。初始化时可以指定许可证的数量,并且可以通过acquire()和release()方法来获取和释放许可证。
importjava.util.concurrent.Semaphore;publicclassSemaphoreExample{publicstaticvoidmain(String[]args)throwsInterruptedException{// 最多允许3个线程同时访问资源Semaphoresemaphore=newSemaphore(3);for(inti=0;i<5;i++){newThread(()->{try{// 尝试获取许可证,如果无可用许可证则阻塞semaphore.acquire();System.out.println(Thread.currentThread().getName()+" is accessing the resource.");Thread.sleep(1000);}catch(InterruptedExceptione){Thread.currentThread().interrupt();}finally{// 释放许可证semaphore.release();}}).start();}}}运行结果:
Thread-0 is accessing the resource. Thread-1 is accessing the resource. Thread-2 is accessing the resource. ...4.2 Semaphore的注意事项
- 公平性:默认情况下,
Semaphore是非公平的,可能会导致某些线程长时间被阻塞。 - 可重用:许可证可以被多次获取和释放。
总结
在Java并发编程中,CountDownLatch、CyclicBarrier和Semaphore是非常有用的工具类。它们可以帮助我们更好地控制线程的同步与协作。
CountDownLatch适用于需要等待多个任务完成后再继续执行的场景。CyclicBarrier适用于需要让多个线程在某个点上互相等待的场景,而且可以重复使用。Semaphore适用于需要限制同时访问某资源的线程数量的场景。
📚 领取 | 1000+ 套高质量面试题大合集(无套路,闫工带你飞一把)!
成体系的面试题,无论你是大佬还是小白,都需要一套JAVA体系的面试题,我已经上岸了!你也想上岸吗?
闫工精心准备了程序准备面试?想系统提升技术实力?闫工精心整理了1000+ 套涵盖前端、后端、算法、数据库、操作系统、网络、设计模式等方向的面试真题 + 详细解析,并附赠高频考点总结、简历模板、面经合集等实用资料!
✅ 覆盖大厂高频题型
✅ 按知识点分类,查漏补缺超方便
✅ 持续更新,助你拿下心仪 Offer!
📥免费领取👉 点击这里获取资料
已帮助数千位开发者成功上岸,下一个就是你!✨