这是我一直用于工厂的基本模式的示例,它返回一个线程安全的Singleton:
public class UserServiceFactory {
private volatile static UserService userService;
private UserServiceFactory() { }
public static UserService getInstance() {
if (userService == null) {
synchronized(UserServiceImpl.class) {
if (userService == null) {
userService = new UserServiceImpl();
}
}
}
return userService;
}
}
Run Code Online (Sandbox Code Playgroud)
它使用volatile和double check惯用法来确保创建单个实例并在线程中可见.
是否有更简洁和/或更便宜的方式来实现1.6+中的相同目标.
在问题中什么是在Java中实现单例模式的有效方法?最赞成的回答是,使用Enum来实现单例.
这很好,我理解这些论点,分别是语言优势.
但是,我有一组我定义单例但需要扩展其他类的类,这对于枚举方法是不可能的,因为枚举不能子类化.
约书亚布洛赫在他的幻灯片中说:
- 但是缺少一件事 - 你无法扩展枚举类型
- 在大多数情况下,你不应该
- 一个引人注目的用例操作代码
在大多数情况下你不应该:有人可以详细说明吗?我已经实现了几个servlet并扩展了HttpServlet,为什么这些不应该是单例?我只想在我的应用程序中使用它们的一个实例.
这是我第一次Factory上课.下面是我的Factory类,我不确定这是否是制作线程安全的Singleton Factory类的正确方法.我将使用这个工厂返回我客户的实例?
public class ClientFactory {
private static ClientFactory instance = null;
private ClientFactory() {
}
public static ClientFactory getInstance() {
if (instance == null)
{
instance = new ClientFactory();
}
return instance;
}
public IClient getClient() {
return new TestClient();
}
}
Run Code Online (Sandbox Code Playgroud)
这是我的TestClient类 -
public class TestClient implements IClient {
}
Run Code Online (Sandbox Code Playgroud)
这就是我将如何使用我的工厂 -
IClient client = ClientFactory.getInstance().getClient();
Run Code Online (Sandbox Code Playgroud) 注意:请不要将此问题标记为重复.我已经经历了几个类似的问题,但找不到满意的答案.
我一直在研究使用Sqlite数据库的应用程序.我们遵循单例模式,确保我们只能在整个应用程序中创建一个辅助类实例.
public class CustomSqliteHelper extends SQLiteOpenHelper {
public static CustomSqliteHelper getInstance(Context context) {
if (instance == null) {
synchronized (CustomSqliteHelper.class) {
if (instance == null) {
instance = new CustomSqliteHelper(context);
}
}
}
return instance;
}
}
Run Code Online (Sandbox Code Playgroud)
但有时应用程序崩溃了SQLiteDatabaseLockedException.我理解当多个线程/进程尝试一次写入数据库时会出现此异常.即使一个线程/进程在写操作仍在进行时尝试读取数据库,也会抛出此异常.
所以我一直在阅读很多关于这个以及防止这种情况发生的可能方法.很多帖子建议使用ContentProvider而不是直接扩展SqliteOpenHelper类和对数据库对象执行操作.在阅读其中一篇帖子时,这篇文章提到在使用Content Provider时,您不需要手动处理多线程环境.
虽然ContentProvider缺乏线程安全性,但通常您会发现在防止潜在的竞争条件方面您无需采取进一步行动.规范示例是您的ContentProvider由SQLiteDatabase支持的时间; 当两个线程同时尝试写入数据库时,SQLiteDatabase将自行锁定,确保一个等待直到另一个完成.每个线程都将获得对数据源的互斥访问,从而确保满足线程安全性.
以上引用似乎令人困惑,因为首先它提到ContentProvider不支持线程安全.但他总结说,应用程序开发人员不需要做任何事情来实现并发.
另外,如果我选择使用SqliteOpenHelper,那么防止这些崩溃的最佳方法是什么?我一直在考虑为每个db操作使用锁.
public class CustomSqliteHelper extends SQLiteOpenHelper {
private String lock = "lock";
public void insert(){
synchronized(lock){
// Do the insert operation here.
}
}
public void update(){
synchronized(lock){
// Do …Run Code Online (Sandbox Code Playgroud) 我需要在并发环境中延迟加载资源.加载资源的代码只能执行一次.
这两个双重检查锁定(使用JRE 5+和volatile关键字)和初始化按需持有者成语似乎适合这个职业.
仅仅通过查看代码,按需初始化持有者习惯看起来更干净,更有效(但是嘿,我猜这里).不过,我必须小心并记录我的每一个单身人士的模式.至少在我看来,很难理解为什么代码会在现场写出来......
我的问题是:哪种方法更好?为什么?如果你的答案是否定的.您将如何在Java SE环境中解决此要求?
备择方案
我可以使用CDI而不强制它在整个项目中使用吗?那里有文章吗?
我最近在接受以下代码的采访时被问及java相关问题,因为我对Java很新,而且几乎没有Java代码,所以我真的不知道下面的代码是做什么的.
问题是使用以下代码选择描述最糟糕事情的选项:
public class Bolton {
private static Bolton INST = null;
public static Bolton getInstance()
{
if ( INST == null )
{
INST = new Bolton();
}
return INST;
}
private Bolton() {
}
}
Run Code Online (Sandbox Code Playgroud)
以下是此问题的选项
- 可以创建多个Bolton实例
- 永远不会创造博尔顿
- 构造函数是私有的,无法调用
- 可以对值进行垃圾回收,并且对getInstance的调用可能会返回垃圾数据
以上哪个选项是正确的?为什么?
对于Spring,如果我有两个同时访问singleton bean的请求怎么办?一个请求是否必须等到另一个请求完成.Spring容器如何为我的请求找到单例bean实例?
对于servlet,如果我有两个请求同时访问普通类的正常方法(没有静态没有其他复杂的东西)?一个请求是否必须等到另一个请求完成以避免并发(同时两个请求正在尝试访问同一类的对象).Web容器如何找到我的请求的实例?
Peter Lawrey撰写了大多数人在他的博客上遗忘的两个Enums of Enums.
首先,我没有忘记 - 我甚至没有意识到:)
这些方法简洁明了 - 与更传统的实现相同方法的方法相比,除了简洁之外还有什么好处,比如使用final带有private实用程序类构造函数的类?
此外,是否有任何问题(除了令人困惑的程序员不期待它)?
枚举被认为是单身人士的最佳方式,其中一个原因是它隐含地继承了Serializable.
但是enums如何防止单身人员的反序列化问题?
我有一个单身人士课程:
public class School {
private HashMap<String, String> students;
private static School school;
private School(){
students = new HashMap<String, String>();
}
public static School getInstance(){
if(school == null){
school = new School();
}
return school;
}
//Method to add student
protected void addStudent(String id, String name){
students.put(id,name);
}
//Method to remove student
protected void removeStudent(String id){
students.remove(id);
}
}
Run Code Online (Sandbox Code Playgroud)
正如您在上面所看到的,在单例类中,我有一个students变量(a HashMap),有一些方法可以在类中添加和删除学生.
在我的应用程序,有可能是使用这个多线程School类getInstance(),然后添加和删除学生.为了使访问(特别是对 students 实例的访问)是线程安全的,我想在方法中使用synchorized关键字getInstanc(),如: …
java ×10
singleton ×7
enums ×3
servlets ×2
android ×1
concurrency ×1
factory ×1
lazy-loading ×1
performance ×1
spring ×1
sqlite ×1