Java 如何修改类设计以使其线程安全
我在想,我的设计可能会让我陷入一种无法保证线程安全的境地。如果是这样的话,有人可能会提供一些建议来改变这种情况吗 我有一个代表当前投标人的类Java 如何修改类设计以使其线程安全,java,multithreading,concurrency,thread-safety,Java,Multithreading,Concurrency,Thread Safety,我在想,我的设计可能会让我陷入一种无法保证线程安全的境地。如果是这样的话,有人可能会提供一些建议来改变这种情况吗 我有一个代表当前投标人的类 public final class Bidders { private static volatile ConcurrentMap<String, BidValue> bidders = new ConcurrentHashMap<String, BidValue>(); public Bidders(Conc
public final class Bidders {
private static volatile ConcurrentMap<String, BidValue> bidders = new ConcurrentHashMap<String, BidValue>();
public Bidders(ConcurrentMap<String, BidValue currentBidders){
if(bidders != null){
bidders = currentBidders;
}
}
public static synchronized ConcurrentMap<String, BidValue> getBidders(){
return bidders;
}
public static synchronized void updateBidder(String bidderName, BidValue value){
if(value != null){
bidders.put(bidderName, value);
}
}
}
例如,我可以预见,使用updatebidder可能会对映射进行修改,而getBidders可能会在完成之前被调用,从而留下不一致的状态。但是,我需要通过我的应用程序访问此状态以进行各种更新
是否有人可以建议我如何以不同的方式/以更好的方式来实现这一点,例如,列举一些我可以研究的技术,以帮助我构建更健壮的应用程序
谢谢
对映射的修改可能会使用updatebidder进行,并且可能会在映射完成之前调用getBidders,从而留下不一致的状态
您使用的是ConcurrentMap,它是为应对这些情况而构建的
静态的使用,在构造函数中注入映射,返回映射,都是巨大的代码气味,但是我不明白为什么你要从发布的有限代码中执行这些操作。我的投标人会这样开始,这是threadsafe,原因在评论中:
public final class Bidders {
// I don't need a concurrent map any longer, I'm in control of the concurrency within
// this class.
private final Map<String, BidValue> bidders = new HashMap<String, BidValue>();
public void updateBidder(String bidderName, BidValue value) {
if (value != null) {
synchronized (this) {
// ensures we do not add while we're enumerating
bidders.put(bidderName, value);
}
}
}
public List<PlayerBid> getBids() {
List<PlayerBid> bids = new ArrayList<PlayerBid>();
synchronized (this) {
// ensures we do not add while we're enumerating,
// if we returned the map
// we couldn't guarantee this would happen.
for (Entry<String, BidValue> entry : bidders.entrySet()) {
bids.add(new PlayerBid(entry.getKey(), entry.getValue()));
}
}
return bids;
}
// add other methods as you need, but avoid returning the internals of
// this class
}
用法:
Bidders.INSTANCE.updateBidder(...);
对映射的修改可能会使用updatebidder进行,并且可能会在映射完成之前调用getBidders,从而留下不一致的状态
您使用的是ConcurrentMap,它是为应对这些情况而构建的
静态的使用,在构造函数中注入映射,返回映射,都是巨大的代码气味,但是我不明白为什么你要从发布的有限代码中执行这些操作。我的投标人会这样开始,这是threadsafe,原因在评论中:
public final class Bidders {
// I don't need a concurrent map any longer, I'm in control of the concurrency within
// this class.
private final Map<String, BidValue> bidders = new HashMap<String, BidValue>();
public void updateBidder(String bidderName, BidValue value) {
if (value != null) {
synchronized (this) {
// ensures we do not add while we're enumerating
bidders.put(bidderName, value);
}
}
}
public List<PlayerBid> getBids() {
List<PlayerBid> bids = new ArrayList<PlayerBid>();
synchronized (this) {
// ensures we do not add while we're enumerating,
// if we returned the map
// we couldn't guarantee this would happen.
for (Entry<String, BidValue> entry : bidders.entrySet()) {
bids.add(new PlayerBid(entry.getKey(), entry.getValue()));
}
}
return bids;
}
// add other methods as you need, but avoid returning the internals of
// this class
}
用法:
Bidders.INSTANCE.updateBidder(...);
你要小心你正在采取的方法。您只不过是将一个已经是线程保存的对象包装起来,并由此产生一种错觉,即您的应用程序变得线程安全。你真的应该看看你的“业务逻辑”,并使线程安全。公开ConcurrentHashMap实际上会破坏线程安全 因此,请研究一种从如下界面开始的方法:
public interface BidManager {
void registerBid (String bidderName, BidValue bidValue);
void stopBids();
boolean hasBid(String bidderName);
void calculateWinningBid();
String getWinnnigBidderName();
BidValue getWinningBidValue();
}
然后从这里开始工作,首先确保您可以以线程安全的方式实现此接口,然后设置一种以线程安全的方式获取这些BidManager对象的方法,可以使用单例模式,也可以通过其他方式 你要小心你正在采取的方法。您只不过是将一个已经是线程保存的对象包装起来,并由此产生一种错觉,即您的应用程序变得线程安全。你真的应该看看你的“业务逻辑”,并使线程安全。公开ConcurrentHashMap实际上会破坏线程安全 因此,请研究一种从如下界面开始的方法:
public interface BidManager {
void registerBid (String bidderName, BidValue bidValue);
void stopBids();
boolean hasBid(String bidderName);
void calculateWinningBid();
String getWinnnigBidderName();
BidValue getWinningBidValue();
}
然后从这里开始工作,首先确保您可以以线程安全的方式实现此接口,然后设置一种以线程安全的方式获取这些BidManager对象的方法,可以使用单例模式,也可以通过其他方式 感谢您的回复-我在阅读评论时也这么认为,但避免返回此类的内部内容-但是,如果另一个对象需要了解当前的投标人,那么如果不返回类的内部内容,又不返回关于单例的内部内容,该如何做-这不被视为反模式吗?另一个类需要什么要确切知道?当时有哪些投标人辛格尔顿是,这就是为什么我建议谨慎,但当你声明一个静态字段时,这是整个程序的一个实例,不管怎样,谢谢你的回复-我在阅读评论时也这么认为,但避免返回此类的内部内容-但是,如果另一个对象需要知道当前的投标人,如果不返回类的内部内容,又不返回单例的内部内容,你会怎么做-这不被视为反模式吗?是什么另一个类需要确切地知道?当时有哪些投标人Singleton是,这就是我建议谨慎的原因,但是当你声明一个静态字段时,这是整个程序的一个实例,所以无论如何你都有。