Java 并发工具类:提升多线程编程效率!
开篇语
哈喽,各位小伙伴们,你们好呀,我是喵手。运营社区:C站/掘金/腾讯云/阿里云/华为云/51CTO;欢迎大家常来逛逛
今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互相学习,一个人虽可以走的更快,但一群人可以走的更远。
我是一名后端开发爱好者,工作日常接触到最多的就是Java语言啦,所以我都尽量抽业余时间把自己所学到所会的,通过文章的形式进行输出,希望以这种方式帮助到更多的初学者或者想入门的小伙伴们,同时也能对自己的技术进行沉淀,加以复盘,查缺补漏。
小伙伴们在批阅的过程中,如果觉得文章不错,欢迎点赞、收藏、关注哦。三连即是对作者我写作道路上最好的鼓励与支持!
前言
在 Java 中,随着多核处理器和多线程编程的普及,许多并发工具类应运而生,帮助开发者更高效地进行多线程处理。通过合理使用这些并发工具类,可以有效地控制线程的执行顺序、提高性能以及简化复杂的并发场景。本文将详细介绍 Java 中常用的并发工具类,包括 CountDownLatch
、CyclicBarrier
、Semaphore
、阻塞队列(BlockingQueue
)、并发集合(ConcurrentHashMap
和 CopyOnWriteArrayList
)、原子类(AtomicInteger
和 AtomicReference
),以及 Future
和 CompletableFuture
。
1. CountDownLatch
、CyclicBarrier
、Semaphore
1.1 CountDownLatch
CountDownLatch
是一个同步工具类,它允许一个或多个线程等待直到其他线程执行完某些操作。通常用于“等待其他线程完成任务后再继续”。
主要方法:
countDown()
:减少计数器的值。await()
:使当前线程等待,直到计数器的值为 0。
使用场景:例如,主线程等待子线程完成初始化工作后再执行。
import java.util.concurrent.CountDownLatch;
public class CountDownLatchExample {
public static void main(String[] args) throws InterruptedException {
CountDownLatch latch = new CountDownLatch(3);
// 启动 3 个子线程
for (int i = 0; i < 3; i++) {
new Thread(() -> {
System.out.println("Thread is ready");
latch.countDown(); // 减少计数
}).start();
}
latch.await(); // 主线程等待,直到计数为 0
System.out.println("All threads are ready, now main thread can proceed");
}
}
1.2 CyclicBarrier
CyclicBarrier
是一个同步辅助工具类,它使得一组线程相互等待,直到所有线程都到达某个公共屏障点。与 CountDownLatch
不同,CyclicBarrier
是可重用的,可以重复使用。
主要方法:
await()
:使当前线程等待,直到所有线程到达屏障点。reset()
:重置屏障。
使用场景:用于多线程并行执行某些任务,然后在某个时刻等待所有线程都完成某个操作后再继续执行。
import java.util.concurrent.CyclicBarrier;
public class CyclicBarrierExample {
public static void main(String[] args) throws InterruptedException {
int threadsCount = 3;
CyclicBarrier barrier = new CyclicBarrier(threadsCount, () -> {
System.out.println("All threads are ready, let's continue execution");
});
// 启动 3 个子线程
for (int i = 0; i < threadsCount; i++) {
new Thread(() -> {
try {
System.out.println(Thread.currentThread().getName() + " is doing some work");
barrier.await(); // 等待其他线程
} catch (Exception e) {
e.printStackTrace();
}
}).start();
}
}
}
1.3 Semaphore
Semaphore
是一个计数信号量,用于控制同时访问某个特定资源的线程数量。信号量可以用来限制线程数,防止系统超负荷。
主要方法:
acquire()
:获取信号量,成功获取后计数减 1。release()
:释放信号量,计数加 1。
使用场景:控制对数据库、文件、网络等共享资源的并发访问。
import java.util.concurrent.Semaphore;
public class SemaphoreExample {
public static void main(String[] args) throws InterruptedException {
Semaphore semaphore = new Semaphore(3); // 限制最多 3 个线程并发访问
// 启动 5 个线程
for (int i = 0; i < 5; i++) {
new Thread(() -> {
try {
semaphore.acquire(); // 获取信号量
System.out.println(Thread.currentThread().getName() + " is working");
Thread.sleep(1000);
semaphore.release(); // 释放信号量
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}
}
}
2. 阻塞队列 (BlockingQueue)
BlockingQueue
是一个线程安全的队列,它支持在队列为空时进行阻塞的读取操作,在队列满时进行阻塞的写入操作。常用的实现类有:
ArrayBlockingQueue
LinkedBlockingQueue
PriorityBlockingQueue
DelayQueue
常用方法:
put()
:将元素插入队列,如果队列满则等待。take()
:从队列取出元素,如果队列为空则等待。offer()
:尝试插入元素,若队列已满则返回false
。poll()
:尝试取出元素,若队列为空则返回null
。
使用场景:适用于生产者-消费者模型,其中生产者和消费者之间通过队列进行数据交换。
import java.util.concurrent.ArrayBlockingQueue;
public class BlockingQueueExample {
public static void main(String[] args) throws InterruptedException {
ArrayBlockingQueue<Integer> queue = new ArrayBlockingQueue<>(3);
// 生产者线程
new Thread(() -> {
try {
for (int i = 0; i < 5; i++) {
queue.put(i); // 阻塞队列满时会阻塞
System.out.println("Produced: " + i);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
// 消费者线程
new Thread(() -> {
try {
for (int i = 0; i < 5; i++) {
Integer item = queue.take(); // 阻塞队列空时会阻塞
System.out.println("Consumed: " + item);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}
}
3. 并发集合 (ConcurrentHashMap, CopyOnWriteArrayList)
3.1 ConcurrentHashMap
ConcurrentHashMap
是一个线程安全的哈希表,它支持高效的并发访问,适合在多线程环境下对映射数据进行操作。它通过分段锁定的方式,使得多个线程可以同时访问不同段的数据。
import java.util.concurrent.ConcurrentHashMap;
public class ConcurrentHashMapExample {
public static void main(String[] args) {
ConcurrentHashMap<String, String> map = new ConcurrentHashMap<>();
map.put("key1", "value1");
map.put("key2", "value2");
map.forEach((key, value) -> System.out.println(key + ": " + value));
}
}
3.2 CopyOnWriteArrayList
CopyOnWriteArrayList
是一个线程安全的列表实现,采用“写时复制”的策略。当修改操作(如 add()
、remove()
)发生时,CopyOnWriteArrayList
会复制底层数组,以确保其他线程可以并发读取而不受影响。适用于读取多、写入少的场景。
import java.util.concurrent.CopyOnWriteArrayList;
public class CopyOnWriteArrayListExample {
public static void main(String[] args) {
CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();
list.add("apple");
list.add("banana");
list.forEach(System.out::println);
}
}
4. 原子类 (AtomicInteger, AtomicReference)
原子类是通过底层的硬件原子操作,来确保多线程环境下对变量的操作是线程安全的。AtomicInteger
和 AtomicReference
是常用的原子类,分别用于整数类型和对象引用类型的线程安全操作。
4.1 AtomicInteger
AtomicInteger
提供了原子性操作,例如递增、递减、加减等。
import java.util.concurrent.atomic.AtomicInteger;
public class AtomicIntegerExample {
public static void main(String[] args) {
AtomicInteger atomicInt = new AtomicInteger(0);
System.out.println(atomicInt.incrementAndGet()); // 原子递增
}
}
4.2 AtomicReference
AtomicReference
用于原子性地更新对象引用,确保在并发环境下对对象的操作是线程安全的。
import java.util.concurrent.atomic.AtomicReference;
public class AtomicReferenceExample {
public static void main(String[] args) {
AtomicReference<String> atomicRef = new AtomicReference<>("Hello");
atomicRef.set("World");
System.out.println(atomicRef.get());
}
}
5. Future
和 CompletableFuture
5.1 Future
Future
是用于表示一个异步计算结果的接口,可以通过它来获取计算结果、取消任务或检查任务的完成状态。
import java.util.concurrent.*;
public class FutureExample {
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<Integer> future = executor.submit(() -> 42);
// 获取计算结果
Integer result = future.get();
System.out.println("Result: " + result);
executor.shutdown();
}
}
5.2 CompletableFuture
CompletableFuture
是 Future
的扩展,它提供了更多的异步操作,如 thenApply()
、thenAccept()
等,支持更复杂的异步流控制。
import java.util.concurrent.CompletableFuture;
public class CompletableFutureExample {
public static void main(String[] args) {
CompletableFuture.supplyAsync(() -> "Hello")
.thenApply(result -> result + " World")
.thenAccept(System.out::println);
}
}
CompletableFuture
可以进行多个异步操作的组合,并且支持链式调用,适用于复杂的异步任务处理。
总结
Java 提供了丰富的并发工具类来帮助开发者简化多线程编程的复杂性。通过合理使用 CountDownLatch
、CyclicBarrier
、Semaphore
、阻塞队列、并发集合、原子类和 Future
/CompletableFuture
,你可以更高效地控制线程执行顺序、提高性能,并处理复杂的并发场景。掌握这些并发工具类,对于构建高效、可扩展的多线程应用程序至关重要。
… …
文末
好啦,以上就是我这期的全部内容,如果有任何疑问,欢迎下方留言哦,咱们下期见。
… …
学习不分先后,知识不分多少;事无巨细,当以虚心求教;三人行,必有我师焉!!!
wished for you successed !!!
⭐️若喜欢我,就请关注我叭。
⭐️若对您有用,就请点赞叭。
⭐️若有疑问,就请评论留言告诉我叭。
版权声明:本文由作者原创,转载请注明出处,谢谢支持!
- 点赞
- 收藏
- 关注作者
评论(0)