Java 多线程等待的最佳实践
我正在使用spring框架编写一个应用程序。我有一个用户管理应用程序,我可以在其中创建用户及其地址,每个用户及其地址接收一个ID,该ID使用另一个类生成。因为每个ID生成都需要时间,所以我想在线程中创建ID。我希望每个地址的创建都要等到它的ID准备好了,用户也准备好了 尝试使用wait,但有时看起来不太顺利,我不是所有地址都要等到全部完成,我更喜欢每次等待都只等待它自己的IDJava 多线程等待的最佳实践,java,multithreading,Java,Multithreading,我正在使用spring框架编写一个应用程序。我有一个用户管理应用程序,我可以在其中创建用户及其地址,每个用户及其地址接收一个ID,该ID使用另一个类生成。因为每个ID生成都需要时间,所以我想在线程中创建ID。我希望每个地址的创建都要等到它的ID准备好了,用户也准备好了 尝试使用wait,但有时看起来不太顺利,我不是所有地址都要等到全部完成,我更喜欢每次等待都只等待它自己的ID public UserDto createUser(UserDto userDto) { UserEntit
public UserDto createUser(UserDto userDto) {
UserEntity storedUserDetails = userRepository.findByEmail(userDto.getEmail());
if (userRepository.findByEmail(userDto.getEmail()) != null) {
throw new RuntimeException("Record already exists");
}
final String[] userId = new String[1];
final CountDownLatch userIdLatch = new CountDownLatch(1);
int addressesSize = userDto.getAddresses().size();
final String[] addressesId = new String[addressesSize];
final CountDownLatch[] addressesIdLatches = new CountDownLatch[addressesSize];
for (int i = 0; i < addressesSize; i++) {
addressesIdLatches[i] = new CountDownLatch(1);
}
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < addressesSize; i++) {
addressesId[i] = utils.generateAddressId(30);
addressesIdLatches[i].countDown();
}
userId[0] = utils.generateUserId(30);
userIdLatch.countDown();
}
});
thread.start();
for (int i = 0; i < addressesSize; i++) {
AddressDto addressDto = userDto.getAddresses().get(i);
addressDto.setUserDetails(userDto);
try {
addressesIdLatches[i].await();
} catch (InterruptedException e) {
e.printStackTrace();
}
addressDto.setAddressId(addressesId[i]);
userDto.getAddresses().set(i, addressDto);
}
ModelMapper modelMapper = new ModelMapper();
UserEntity userEntity = modelMapper.map(userDto, UserEntity.class);
try {
userIdLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
userEntity.setUserId(userId[0]);
userEntity.setEncryptedPassword(bCryptPasswordEncoder.encode(userDto.getPassword()));
UserEntity storedUserEntity = userRepository.save(userEntity);
UserDto returnedValue = new UserDto();
BeanUtils.copyProperties(storedUserEntity, returnedValue);
return returnedValue;
}
public UserDto createUser(UserDto UserDto){
UserEntity storedUserDetails=userRepository.findByEmail(userDto.getEmail());
if(userRepository.findByEmail(userDto.getEmail())!=null){
抛出新的RuntimeException(“记录已存在”);
}
最终字符串[]userId=新字符串[1];
最终CountDownLatch useridlotch=新的CountDownLatch(1);
int-AddresseSize=userDto.getAddresses().size();
最终字符串[]地址ID=新字符串[地址大小];
最终倒计时闩锁[]地址设置闩锁=新倒计时闩锁[地址设置];
for(int i=0;i
ER->每个地址等待,直到它的ID准备就绪(无需等待其他地址)
AR->抛出异常非常简单的示例
public class Main {
public static void main(String[] args) throws Exception {
User user = new User();
int count = 100;
user.adrs = new String[count];
while (count > 0) {
count--;
user.adrs[count] = "adr" + count;
}
int userAddressesCount = user.adrs.length;
ExecutorService service = Executors.newFixedThreadPool(userAddressesCount);
Map<String, Future<String>> adrMap = new HashMap<>();
for (int i = 0; i < userAddressesCount; i++) {
String oldAdr = user.adrs[i];
adrMap.put(oldAdr, service.submit(new AddressReceiver(oldAdr)));
}
for (String key : adrMap.keySet()) {
int idxOfAdr = user.findIdxOfAdr(key);
//something like enrich address
user.adrs[idxOfAdr] = adrMap.get(key).get();
System.out.println("ASYNC: " + user.adrs[idxOfAdr]);
}
System.out.println("#################################");
for(String adr: user.adrs) {
System.out.println(adr);
}
service.shutdown();
}
static class User {
String id;
String[] adrs;
private int findIdxOfAdr(String adr) {
for (int i = 0; i < this.adrs.length; i++) {
if (this.adrs[i].equals(adr)) return i;
}
return -1;
}
}
static class AddressReceiver implements Callable<String> {
private final String someValueForGeneration;
public AddressReceiver(String someValueForGeneration) {
this.someValueForGeneration = someValueForGeneration;
}
@Override
public String call() throws Exception {
Thread.sleep((int) (Math.random() * 10000));
return someValueForGeneration + " enrich adr";
}
}
公共类主{
公共静态void main(字符串[]args)引发异常{
用户=新用户();
整数计数=100;
user.adrs=新字符串[计数];
而(计数>0){
计数--;
user.adrs[count]=“adr”+计数;
}
int useraddresscount=user.adrs.length;
ExecutorService=Executors.newFixedThreadPool(UserAddressCount);
Map adrMap=新的HashMap();
for(int i=0;i
}在我看来,您的整个多线程解决方案存在缺陷。在这里创建第二个线程有什么意义?除非
setUserDetails()
非常复杂,否则您只是将负载从一个线程移动到另一个线程。也许你应该创建多线程或其他什么?除此之外,使用某种类型的ExecutorService
和Future
s列表可能会使整个应用程序比手动使用Latch
es和await()
更简单。请分享一个最小的可复制示例,以便我们可以帮助你。有关更多详细信息,请查看此链接: