我正在开发一个使用Java EE进行游戏评论的内容管理系统。
我有一个非常简单的问题,现在是:
我有一个带有Game对象的ArrayList。每个游戏对象都有GameRank属性,这是一个像这样定义的简单类:
public class GameRank
{
private int activity;
private int positiveVotes;
private int negativeVotes;
public GameRank(int activity, int positiveVotes, int negativeVotes)
{
this.activity = activity;
this.positiveVotes = positiveVotes;
this.negativeVotes = negativeVotes;
}
}
网站的访问者可以选择对游戏进行正面或负面投票,结果将使用ajax发送到服务器。
所以问题是:
我应该在哪里同步对GameRank对象属性的访问 - 他们的getter和setter方法OR在Controller Servlet中处理用户投票,并根据游戏ID决定哪个对象应该更新?
提前10倍如果我决定在课程中使用同步,我可以使用AtomicInteger作为建议的海报之一或者:
public class GameRank
{
private volatile int activity;
private volatile int positiveVotes;
private volatile int negativeVotes;
public GameRank(int activity, int positiveVotes, int negativeVotes)
{
this.activity = activity;
this.positiveVotes = positiveVotes;
this.negativeVotes = negativeVotes;
this.checkAndFixValues();
}
private void checkAndFixValues()
{
if(this.activity < 1) this.activity = 1;
if(this.positiveVotes < 1) this.positiveVotes = 1;
if(this.negativeVotes < 1) this.negativeVotes = 1;
}
public int getActivity()
{
synchronized(GameRank.class)
{
return activity;
}
}
public int getPositiveVotes()
{
synchronized(GameRank.class)
{
return positiveVotes;
}
}
public int getNegativeVotes()
{
synchronized(GameRank.class)
{
return negativeVotes;
}
}
public void incrementActivitiy()
{
synchronized(GameRank.class)
{
activity++;
}
}
}
我是对的吗?
答案 0 :(得分:3)
在Java-EE中(或者通常在使用servlet时),不同的请求由不同的线程处理。无论这些线程在共享对象上运行,您都需要某种同步。
取决于您的持久性技术,可能是也可能不是。对于JPA,通常为每个线程提供自己的持久性上下文,并检测数据库中的冲突更新。如果这样做,则不需要JVM内的同步,但是如果由于更新冲突导致事务无法提交,则可能需要实现重试逻辑。如果您不跨线程共享JDBC对象(Connection
,Resultset
),则使用JDBC时也是如此。
答案 1 :(得分:0)
外部化线程安全责任的问题是其他客户可以自由地忽略这些问题,破坏所有用法。
最好将这些问题内化,并使你的类线程安全。
幸运的是,JDK提供了一个为您完成所有工作的类:AtomicInteger。如果将计数器的类型更改为AtomicInteger,则可以简单地添加方法以线程安全的方式递增它们。有关更多信息,请参阅AtomicInteger的javadoc。
答案 2 :(得分:-1)
您可以在GameRank中引入同步方法,该方法将接受投票(+ ve或-ve)并相应地更新positiveVotes / negativeVotes。