男儿当入樽正版
1.51 GB · 2025-12-15
在Java并发编程中,有效控制并发度是提高应用性能和资源利用率的关键。本文将通过一个Java示例代码,探讨两种控制并发度的实现方法:竞争队列法和信号量法。我们将详细分析这两种方法的实现原理,并比较它们的优缺点。为降低理解难度,本文不考虑快速失败、任务取消、异常处理、超时控制等问题,这些问题常常基于本文的代码进行拓展。
首先,让我们看看用于生成任务的 getTasks 方法:
private static BlockingQueue<Runnable> getTasks() {
IntFunction<Integer> square = x -> x * x;
BlockingQueue<Runnable> tasks = IntStream.range(0, 10).<Runnable>mapToObj(num -> () -> {
int result = square.apply(num);
System.out.println("The square of " + num + " is " + result);
}).collect(Collectors.toCollection(() -> new ArrayBlockingQueue<>(10)));
return tasks;
}
这个方法创建了一个包含10个任务的 BlockingQueue。每个任务是一个 Runnable 对象,负责计算一个数字的平方并打印结果。这个方法模拟了一个实际场景中的任务队列,每个任务都是独立的且可并行执行的。
现在,让我们讨论两种并发控制方法:
static class RaceQueueDemo {
public static void main(String[] args) {
ExecutorService e = Executors.newCachedThreadPool();
int parallelism = 3; // 并发度
BlockingQueue<Runnable> tasks = getTasks();
for (int i = 0; i < parallelism; i++) {
e.submit(() -> {
Runnable r;
while ((r = tasks.poll()) != null) {
r.run();
}
});
}
e.shutdown();
}
}
这种方法的核心思想是:
优点:
static class SemaphoreDemo {
public static void main(String[] args) {
ExecutorService e = Executors.newCachedThreadPool();
ExecutorService taskSubmitter = Executors.newSingleThreadExecutor();
int parallelism = 3; // 并发度
Semaphore semaphore = new Semaphore(parallelism);
Future<?> submitted = taskSubmitter.submit(() -> {
BlockingQueue<Runnable> tasks = getTasks();
Runnable r;
while ((r = tasks.poll()) != null) {
try {
semaphore.acquire();
Runnable finalR = r;
e.submit(() -> {
try {
finalR.run();
} finally {
semaphore.release();
}
});
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
});
Futures.getUnchecked(submitted);
taskSubmitter.shutdown();
e.shutdown();
}
}
这种方法的核心思想是:
优点:
缺点:
复杂性:竞争队列法实现简单,易于理解和维护;信号量法相对复杂,但提供了更细粒度的控制。
资源利用:信号量法能够更均衡地利用资源,特别是在任务执行时间差异较大的情况下。
异常处理:信号量法更容易处理任务执行过程中的异常情况,而竞争队列法在这方面略显不足。
灵活性:两种方法都允许动态调整并发度,但信号量法在运行时调整并发度更为方便。
性能开销:竞争队列法可能在高并发情况下有更好的性能,因为它减少了线程间的协调开销。
选择哪种方法取决于具体的应用场景:
在实际应用中,可能需要结合这两种方法或使用更高级的并发控制技术来满足特定需求。无论选择哪种方法,都需要根据实际情况进行性能测试和调优,以达到最佳的并发效果。