因此,我正在考虑建立一个爱好项目,一种类似的东西,只是为了了解我的编程/设计。
它基本上是一个多线程的Web蜘蛛,更新相同的数据结构对象 - > int。
因此,使用数据库绝对有点过分,我唯一能想到的就是用于包含数据结构的线程安全单例。 http://web.archive.org/web/20121106190537/http://www.ibm.com/developerworks/java/library/j-dcl/index.html
我应该考虑采用不同的方法吗?
答案 0 :(得分:30)
双重检查锁定已被证明是错误的和有缺陷的(至少在Java中)。进行搜索或查看Wikipedia's entry的确切原因。
首先是程序的正确性。如果您的代码不是线程安全的(在多线程环境中),那么它就会被破坏。在性能优化之前,首先是正确性。
为了更正,您必须同步整个getInstance
方法
public static synchronized Singleton getInstance() {
if (instance==null) ...
}
或静态初始化
private static final Singleton INSTANCE = new Singleton();
答案 1 :(得分:10)
对Web爬网程序中的数据库使用延迟初始化可能不值得。延迟初始化增加了复杂性和持续的速度命中。一个合理的案例是,很有可能永远不需要数据。此外,在交互式应用程序中,它可用于减少启动时间并提供错觉的速度。
对于像web-crawler这样的非交互式应用程序,它肯定需要立即存在其数据库,懒惰初始化是不合适的。
另一方面,Web爬虫很容易并行化,并且可以从多线程中受益匪浅。使用它作为掌握java.util.concurrent
库的练习将是非常值得的。具体来说,请查看ConcurrentHashMap
和ConcurrentSkipListMap
,,这将允许多个线程读取和更新共享地图。
当您摆脱延迟初始化时,最简单的Singleton模式是这样的:
class Singleton {
static final Singleton INSTANCE = new Singleton();
private Singleton() { }
...
}
关键字final
是此处的关键。即使你为单例提供static
“getter”而不是允许直接字段访问,使单例final
有助于确保正确性并允许JIT编译器进行更积极的优化。
答案 2 :(得分:2)
如果您的生活依赖于几微秒,那么我建议您优化资源锁定到实际重要的位置。
但在这种情况下,这里的关键字是爱好项目!
这意味着,如果您同步整个 getInstance()方法,那么在99.9%的情况下你都可以。我不建议任何其他方式。
稍后,如果您通过分析证明 getInstance()同步是项目的瓶颈,那么您可以继续并优化并发性。但我真的怀疑它会给你带来麻烦。
Jeach!
答案 3 :(得分:2)
尝试 Bill Pugh 解决方案初始化按需持有人习惯用法。 该解决方案在不同的Java编译器和虚拟机中最易于移植。 该解决方案是线程安全的,无需特殊的语言结构(即易失性和/或同步)。
http://en.wikipedia.org/wiki/Singleton_pattern#The_solution_of_Bill_Pugh
答案 4 :(得分:2)
public enum Singleton {
INSTANCE;
public void doSomething() { ... }
}
答案 5 :(得分:1)
如果您查看该文章的最底部,您将看到仅使用静态字段的建议。这将是我的倾向:你并不需要懒惰的实例化(因此你不需要getInstance()
同时成为访问者和工厂方法)。您只想确保您拥有其中一项且仅有一项。如果你真的需要全局访问这样的东西,我会使用that code sample towards the very bottom:
class Singleton
{
private Vector v;
private boolean inUse;
private static Singleton instance = new Singleton();
private Singleton()
{
v = new Vector();
inUse = true;
//...
}
public static Singleton getInstance()
{
return instance;
}
}
请注意,现在在安装静态字段期间构建了Singleton。这应该有效,而不是面临潜在的错误同步的线程风险。
所有这些,也许你真正需要的是现代JDK中可用的线程安全数据结构之一。例如,我是ConcurrentHashMap的忠实粉丝:线程安全加上我不必编写代码(FTW!)。
答案 6 :(得分:1)
为什么不创建一个作为依赖注入传递给每个线程的数据结构。这样你就不需要单身人士了。你仍然需要使线程安全。
答案 7 :(得分:0)
您引用的文章仅讨论如何创建单例对象,在本例中可能是一个集合,是线程安全的。您还需要一个线程安全的集合,以便集合操作也按预期工作。确保单例中的基础集合是同步的,可能使用ConcurrentHashMap。
答案 8 :(得分:0)
查看此文章Implementing the Singleton Pattern in C#
public sealed class Singleton
{
Singleton()
{
}
public static Singleton Instance
{
get
{
return Nested.instance;
}
}
class Nested
{
// Explicit static constructor to tell C# compiler
// not to mark type as beforefieldinit
static Nested()
{
}
internal static readonly Singleton instance = new Singleton();
}
}
答案 9 :(得分:0)
怎么样:
public static Singleton getInstance() {
if (instance == null) {
synchronize(Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}