从Head First设计模式书中,具有双重检查锁定的单例模式已实现如下:
public class Singleton {
private volatile static Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
Run Code Online (Sandbox Code Playgroud)
我不明白为什么volatile被使用.volatile使用不会 破坏使用双重检查锁定的目的,即性能?
java singleton design-patterns locking double-checked-locking
单身人士是一个备受争议的设计模式,所以我对Stack Overflow社区对它们的看法感兴趣.
请提供您的意见的原因,而不仅仅是"单身人士是懒惰的程序员!"
这是一篇关于这个问题的相当不错的文章,虽然它反对使用Singletons: scientificninja.com:performant-singletons.
有没有人对他们有任何其他好文章?也许是为了支持单身人士?
单身类的通常模式就像
static Foo &getInst()
{
static Foo *inst = NULL;
if(inst == NULL)
inst = new Foo(...);
return *inst;
}
Run Code Online (Sandbox Code Playgroud)
但是,我的理解是这个解决方案不是线程安全的,因为1)Foo的构造函数可能被多次调用(可能或可能不重要)和2)inst在返回到不同的线程之前可能没有完全构造.
一种解决方案是围绕整个方法包装一个互斥锁,但是在我真正需要它之后很长时间我就要付出同步开销.另一种选择是
static Foo &getInst()
{
static Foo *inst = NULL;
if(inst == NULL)
{
pthread_mutex_lock(&mutex);
if(inst == NULL)
inst = new Foo(...);
pthread_mutex_unlock(&mutex);
}
return *inst;
}
Run Code Online (Sandbox Code Playgroud)
这是正确的做法,还是我应该注意哪些陷阱?例如,是否存在可能发生的静态初始化顺序问题,即在第一次调用getInst时,inst总是保证为NULL?
这是我的单例模式的自定义类.在这段代码中,我使用双重检查锁定如下.当我在某些源上阅读很多帖子时,他们说双重检查很有用,因为它可以防止两个并发线程同时运行产生两个不同的对象.
public class DoubleCheckLocking {
public static class SearchBox {
private static volatile SearchBox searchBox;
// private constructor
private SearchBox() {}
// static method to get instance
public static SearchBox getInstance() {
if (searchBox == null) { // first time lock
synchronized (SearchBox.class) {
if (searchBox == null) { // second time lock
searchBox = new SearchBox();
}
}
}
return searchBox;
}
}
Run Code Online (Sandbox Code Playgroud)
我仍然不太了解上面的代码.如果两个线程在实例为空时一起运行相同的代码行,会出现什么问题?
if (searchBox == null) {
synchronized (SearchBox.class) {
if (searchBox == null) {
searchBox = …Run Code Online (Sandbox Code Playgroud) 在Codeigniter中,get_instance()是一个全局可用的函数,它返回包含所有当前加载的类的Controller超级对象(它返回Controller类实例).我将包含当前的源代码:
get_instance() 定义于 Codeigniter.php
// Load the base controller class
require BASEPATH.'core/Controller.php';
function &get_instance()
{
return CI_Controller::get_instance();
}
Run Code Online (Sandbox Code Playgroud)
并CI_Controller定义于Controller.php
class CI_Controller {
private static $instance;
/**
* Constructor
*/
public function __construct()
{
self::$instance =& $this;
// Assign all the class objects that were instantiated by the
// bootstrap file (CodeIgniter.php) to local class variables
// so that CI can run as one big super object.
foreach (is_loaded() as $var => $class)
{
$this->$var =& …Run Code Online (Sandbox Code Playgroud) 我写了一个下面的Singleton类.我不确定这是否是线程安全的单例类?
public class CassandraAstyanaxConnection {
private static CassandraAstyanaxConnection _instance;
private AstyanaxContext<Keyspace> context;
private Keyspace keyspace;
private ColumnFamily<String, String> emp_cf;
public static synchronized CassandraAstyanaxConnection getInstance() {
if (_instance == null) {
_instance = new CassandraAstyanaxConnection();
}
return _instance;
}
/**
* Creating Cassandra connection using Astyanax client
*
*/
private CassandraAstyanaxConnection() {
context = new AstyanaxContext.Builder()
.forCluster(ModelConstants.CLUSTER)
.forKeyspace(ModelConstants.KEYSPACE)
.withAstyanaxConfiguration(new AstyanaxConfigurationImpl()
.setDiscoveryType(NodeDiscoveryType.RING_DESCRIBE)
)
.withConnectionPoolConfiguration(new ConnectionPoolConfigurationImpl("MyConnectionPool")
.setPort(9160)
.setMaxConnsPerHost(1)
.setSeeds("127.0.0.1:9160")
)
.withAstyanaxConfiguration(new AstyanaxConfigurationImpl()
.setCqlVersion("3.0.0")
.setTargetCassandraVersion("1.2"))
.withConnectionPoolMonitor(new CountingConnectionPoolMonitor())
.buildKeyspace(ThriftFamilyFactory.getInstance());
context.start();
keyspace = context.getEntity();
emp_cf = …Run Code Online (Sandbox Code Playgroud) 假设我在主页面级别编写代码,并且2个依赖项需要对象的相同实例,并且还将其声明为依赖项.适当的方法是什么?
基本上我想要做的就是说,"如果没有加载这个依赖...然后加载它.否则,使用已加载的同一个实例,然后传递那个."
我正在阅读有关此问题的stackoverflow,但我仍然没有找到解决方案.我注意到有时,我的应用程序会抛出此错误:
java.lang.IllegalStateException: Cannot perform this operation because the connection pool has been closed.
at android.database.sqlite.SQLiteConnectionPool.throwIfClosedLocked(SQLiteConnectionPool.java:962)
at android.database.sqlite.SQLiteConnectionPool.waitForConnection(SQLiteConnectionPool.java:599)
at android.database.sqlite.SQLiteConnectionPool.acquireConnection(SQLiteConnectionPool.java:348)
at android.database.sqlite.SQLiteSession.acquireConnection(SQLiteSession.java:894)
...
Run Code Online (Sandbox Code Playgroud)
我有一个名为DatabaseHelper.java的文件,使用这种方法获取它的实例:
public static DatabaseHelper getInstance(Context context) {
if (mInstance == null) {
mInstance = new DatabaseHelper(context.getApplicationContext());
}
return mInstance;
}
Run Code Online (Sandbox Code Playgroud)
然后我有像这样的方法(它在行cursor.moveToFirst()中崩溃与该错误).它几乎从不崩溃,但有时它会崩溃.
public Profile getProfile(long id) {
SQLiteDatabase db = this.getReadableDatabase();
String selectQuery = "SELECT * FROM " + TABLE_PROFILES + " WHERE " + KEY_PROFILES_ID + " = " + id;
Cursor cursor = db.rawQuery(selectQuery, null);
// looping …Run Code Online (Sandbox Code Playgroud) 今天我的一个朋友问我为什么他更喜欢在全局静态对象上使用单例?我开始解释的方式是单例可以有状态与静态全局对象不会......但后来我不确定...因为这在C++中...(我来自C#)
一个优于另一个有什么优势?(在C++中)
可能重复:
单身人士有什么不好的?
可以理解的是,许多设计模式在某些情况下可能被滥用,就像妈妈总是说:" 太多好事并不总是好的! "
我注意到这些天,我经常使用Singletons,而且我担心自己可能会滥用设计模式,并且越来越深入地研究一种不良习惯的习惯.
我们正在开发一个Flex应用程序,当用户使用它时,该应用程序在内存中保留了相当大的分层数据结构.用户可以按需加载,保存,更改和刷新数据.
这些数据通过Singleton类集中,该类聚合了几个ArrayCollections,Arrays,value对象以及通过getter和setter公开的一些其他本机成员变量.
要从应用程序的任何位置获取对数据的引用,我们执行整个Model.getInstance()方法类型的事情,我确信每个人都熟悉.这确保了我们始终掌握相同的数据副本,因为在我们设计时,我们说在应用程序生命周期中只允许存在一次实例.
从这个中央数据存储库中,我们可以轻松地调度属性更改事件,并且可以有多个引用中央数据的UI组件,更新其显示以反映已发生的数据更改.
到目前为止,这种方法已经有效并且证明对我们的环境非常实用.
然而,我发现,在创建新课程时,我有点过分了.问题应该是一个类是Singleton,还是应该以其他方式管理,例如可能使用工厂,往往有点变得有点困难,有点不确定.
我在哪里画单线?是否有一个很好的指导方针来决定何时使用单身人士以及何时远离他们.
另外,有人可以推荐一本关于设计模式的好书吗?