我有以下代码片段,包含 2 个不同的方法,这两个方法将被许多线程访问(getWeapon() 和 returnWeapon())。
请任何能够回答以下部分或全部问题的人: 1. 如何使其尽可能高效? 2.我可以不使用synchronized block 吗? 3. 使用不同的对象作为synchronizd block 的键是否更好? 4. 对于这种并发多线程情况,使用ReentrantLock/ReadWriteLock是否更好?
private static final int M16_NUM_WEAPONS = 2;
private static final int AK47_NUM_WEAPONS = 5;
private static final int UZI_NUM_WEAPONS = 9;
private Map<Class<? extends Weapon>, Integer> WeaponsToAmountMap;
public Arsenal() {
this.synchronizedWeaponsToAmountMap = new ConcurrentHashMap<Class<? extends Weapon>, Integer>();
}
public void initializeWeapons() {
synchronizedWeaponsToAmountMap.put(M16.class, M16_NUM_WEAPONS);
synchronizedWeaponsToAmountMap.put(AK47.class, AK47_NUM_WEAPONS);
synchronizedWeaponsToAmountMap.put(Uzi.class, UZI_NUM_WEAPONS);
}
public Weapon getWeapon(Fighter fighter) {
List<Class<? extends Weapon>> allowedWeapons = new ArrayList<>(fighter.getAllowedWeapons());
Class<? extends Weapon> weaponClass = null;
for (Class<? extends Weapon> allowedWeapon : allowedWeapons){
synchronized (this) {
Integer amount = synchronizedWeaponsToAmountMap.get(allowedWeapon);
if (amount != null && amount > 0) {
synchronizedWeaponsToAmountMap.put(allowedWeapon, amount - 1);
System.out.println("Taking : "+allowedWeapon.getSimpleName());
weaponClass = allowedWeapon;
break;
}
}
}
if (weaponClass==null){
return null;
}
Weapon weapon = null;
try {
weapon = weaponClass.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return weapon;
}
public void returnWeapon(Weapon weapon) {
if (weapon==null){
return;
}
synchronized(this) {
System.out.println("returning : "+weapon.getClass().getSimpleName());
synchronizedWeaponsToAmountMap.put(weapon.getClass(), synchronizedWeaponsToAmountMap.get(weapon.getClass()) + 1);
}
}
最佳答案
我认为同步是在一个监视器对象上还是在不同的监视器对象上完成并没有太大区别:只要您想防止不同线程同时访问相同的共享数据,您就可以使用同步,它会线性化访问,然后增加时间。
java.util.concurrent 功能通常和 Reentrant/ReadWriteLock 特别使用非阻塞方法,然后可能会更快 - 但是否完全取决于线程如何与共享数据交互......
关于java - HashMap 通过 2 种不同的方法进行操作 - 多线程和并发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49431426/