单例在Glassfish服务器中实例化两次
问题描述:
我的单例称为资源。它只能由我用这个标准辛格尔顿一次实例:单例在Glassfish服务器中实例化两次
package site.kevindhu.models;
import site.kevindhu.entity.Player;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
public class Resources {
public static Resources resources;
public Map<String, Object> data;
static {
resources = new Resources();
}
private Resources() {
data = new HashMap<>();
data.put("players", new HashSet<Player>());
data.put("newPlayers", new HashSet<Player>());
}
public static Resources getInstance() {
return resources;
}
}
但是,它不能正常工作!
当我部署的.ear运行我的GlassFish服务器,它进入该块两次:
static {
resources = new Resources();
}
其结果是,在“单身”其实每个创建两个不同的资源我运行服务器的时间。
我知道我做了两次,因为我调试时会调用两个不同的Resources对象,只要我尝试调用Resources.resources。
这可能是因为我正在部署一个.ear文件?这个双重实例化的具体细节如何工作?
答
去最好的办法是让编译器为您处理:
/** Singleton. */
public enum Resources {
RESOURCES;
private final Map<String, Team> teams = new HashMap<>();
public boolean add(Team team) {
return team != null
&& teams.put(team.getName(), team) == null;
}
public Team find(String name) {
return name == null ? null : teams.get(name);
}
public Team find(Team team) {
return team == null ? null : get(team.getName());
}
public Map<String, Team> getTeams() {
return Collections.unmodifiableMap(teams);
}
// remove, iterators, etc.
}
public class TeamImpl implements Team {
private final String name;
private final Map<String, Player> roster = new HashMap<>();
public TeamImpl(String name) {
if (name == null) {
throw new IllegalArgumentException("name must not be null");
}
this.name = name;
assert this.name != null;
}
@Override
public boolean equals(Object other) {
// base comparison on team name
}
@Override
public int hashCode() {
assert this.name != null;
return name.hashCode();
}
// methods from interface Team:
@Override
public String getName() {
return name;
}
@Override
public Set<Player> getRoster() {
return Collections.unmodifiableSet(new HashSet<>(roster.values()));
}
@Override
public boolean add(Player player) {
return player != null
&& roster.put(player.getName(), player) == null;
}
@Override
public Player find(String name) {
return name == null ? null : roster.get(name);
}
// remove, iterators, etc.
}
最有可能你的类过得去不同的类加载器加载。根据你写的内容,像这样的自定义单例可能不是应用服务器中最好的想法。 – pvg
我也建议这是一个类加载器问题。 EAR中是否有多个WAR文件?每个人都可能拥有自己的ClassLoader,因此是一个单独的资源实例。请参阅[此答案](https://*.com/a/4132721/3586783)了解更多信息。 – pacifier21
我实际上已将部署更改为.war文件,但仍然存在。 –