
本文旨在解决Java并发编程中,Future对象被错误使用于数据存储和更新的场景。通过分析常见错误用法,阐述Future的正确用途,并提供使用Integer数组替代Future数组的解决方案,同时强调并发环境下数据同步的重要性,帮助开发者避免并发陷阱。
在Java并发编程中,Future接口代表异步计算的结果。它允许我们提交一个任务到ExecutorService,并稍后获取该任务的执行结果。然而,开发者有时会误用Future,例如尝试将Future对象存储在集合中,并期望通过修改Future对象来更新数据。本文将深入探讨这种误用,并提供正确的解决方案。
以下代码片段展示了将Future<Integer>对象存储在List中,并尝试直接修改Future结果的错误做法:
var ex = Executors.newFixedThreadPool(10);
List<Future<Integer>> elements = new ArrayList<>();
for (int i = 0; i < 100; i++) {
elements.add(ex.submit(() -> {
int val = 1000;
return val;
}));
}
ex.shutdown();
int sum = 0;
for (Future<Integer> el : elements) {
try {
sum += el.get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
System.out.println("Initial sum: " + sum);
for (int i = 0; i < 10_000; i++) {
ex.submit(() -> {
int firstIndex = ThreadLocalRandom.current().nextInt(100);
int secondIndex = ThreadLocalRandom.current().nextInt(100);
int randomAmount = ThreadLocalRandom.current().nextInt(1000);
try {
if (elements.get(firstIndex).get() - randomAmount > 0) {
// 错误用法:尝试直接修改 Future 的结果
// elements.set(firstIndex,elements.get(firstIndex).get() - randomAmount);
}
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
});
}这段代码的问题在于:
立即学习“Java免费学习笔记(深入)”;
要解决这个问题,我们需要使用可变的整数数组,并考虑并发安全问题。以下是修改后的代码示例:
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class ConcurrentArrayExample {
public static void main(String[] args) throws InterruptedException {
ExecutorService ex = Executors.newFixedThreadPool(10);
List<Integer> elements = new ArrayList<>();
for (int i = 0; i < 100; i++) {
elements.add(1000);
}
int sum = 0;
for (int el : elements) {
sum += el;
}
System.out.println("Initial sum: " + sum);
// 使用锁保护共享资源
Lock lock = new ReentrantLock();
for (int i = 0; i < 10_000; i++) {
ex.submit(() -> {
int firstIndex = ThreadLocalRandom.current().nextInt(100);
int secondIndex = ThreadLocalRandom.current().nextInt(100);
int randomAmount = ThreadLocalRandom.current().nextInt(1000);
lock.lock(); // 获取锁
try {
if (elements.get(firstIndex) - randomAmount >= 0) {
elements.set(firstIndex, elements.get(firstIndex) - randomAmount);
elements.set(secondIndex, elements.get(secondIndex) + randomAmount); // transfer to second index
}
} finally {
lock.unlock(); // 释放锁
}
});
}
ex.shutdown();
ex.awaitTermination(10, java.util.concurrent.TimeUnit.SECONDS); // 等待所有任务完成
sum = 0;
for (int el : elements) {
sum += el;
}
System.out.println("Final sum: " + sum);
}
}此代码做了以下改进:
在Java并发编程中,理解Future的正确用途至关重要。不要尝试将Future对象用于存储和修改数据。对于需要并发访问和修改的数据,应使用线程安全的数据结构,并采取适当的同步机制。通过本文的分析和示例,希望能帮助开发者避免常见的并发陷阱,编写出更健壮、更可靠的并发程序。
以上就是Java并发编程中Future的误用与解决方案的详细内容,更多请关注php中文网其它相关文章!
编程怎么学习?编程怎么入门?编程在哪学?编程怎么学才快?不用担心,这里为大家提供了编程速学教程(入门课程),有需要的小伙伴保存下载就能学习啦!
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号