gpt4 book ai didi

java - 多线程等待的最佳实践

转载 作者:行者123 更新时间:2023-12-02 01:06:56 25 4
gpt4 key购买 nike

我正在使用 spring 框架编写一个应用程序。我有一个用户管理应用程序,我可以在其中创建用户及其地址,每个用户及其地址都会收到一个使用另一个类生成的 ID。因为每个 ID 生成都需要时间,所以我想在线程中创建 ID。我希望每个地址的创建都等到它的 ID 准备好为止,用户也是如此。

尝试使用等待,但看起来有时不太顺利,我不是所有的地址都等到所有的都完成,我更喜欢每个地址只等待它自己的ID。

 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;
}

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";
}
}

}

关于java - 多线程等待的最佳实践,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57721897/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com