我有一个类“A”,方法是“calculate()”。 A类的类型为singleton(Scope = Singleton)。
public class A{
public void calculate(){
//perform some calculation and update DB
}
}
现在,我有一个创建20个线程的程序。所有线程都需要访问方法“calculate()”。 我有多核系统。所以我想要线程的并行处理。
在上面的场景中,我能获得表现吗?所有线程都可以访问该方法在同一时间进行计算吗?
或者,由于A类是单例,因此需要阻塞线程等待。
我在web / Stackoverflow中发现了类似的问题。但我无法得到明确的答案。 你能帮帮我吗?
答案 0 :(得分:2)
这是Singleton的基本概念。系统中只有一个类实例(JVM)。现在,它取决于calculate()的实现。这是一种无国籍的实用方法吗?如果是,您可能不想让它同步。在这种情况下,多个线程将能够在同一时间访问它。如果calculate()不是无状态的,即它使用实例变量(并且那些实例变量将由多个线程使用),那么要小心;你必须使calculate()线程安全。您必须同步该方法。至少你必须在方法中使用同步块。但是,一旦这样做,任何时候只有一个线程能够访问它(同步块或方法内的同步块)。
public void calculate() {
//Some code goes here which does not need require thread safety.
synchronized(someObj) {
//Some code goes here which requires thread safety.
}
//Some code goes here which does not need require thread safety.
}
如果要使用并行处理(如果这是主要目标),则单例不是您应该使用的设计模式。
答案 1 :(得分:1)
我担心,像“单身人士需要同步”或“单身人士不需要同步”这样的陈述过于简单化了。只能从你处理单身模式的事实中得出结论。
对于多线程而言真正重要的是共享内容。如果执行计算的所有线程共享数据,则可能需要同步该访问。如果代码的关键部分不能在线程之间同时运行,那么您将需要同步它。
好消息是,通常没有必要在整个计算中同步所有内容。尽管需要同步部分操作,您可能会从多核系统中获得显着的性能提升。
坏消息是这些事情非常复杂。抱歉。一个可能的参考:
答案 2 :(得分:1)
我在web / Stackoverflow中发现了类似的问题。但我无法得到明确的答案。
有充分的理由!!
由于单身,无法确定单身人士的方法是否需要同步。
用于同步的同步和需要是关于可以由不同线程共享的状态。
如果不同的线程共享状态(甚至是串行),则需要同步。
如果没有,则不需要同步。
您提供给我们的唯一线索可以帮助我们给您一个是/否答案,这是一个神秘的评论:
// perform some calculation and update DB
......以及calculate()
方法不带参数的事实。
如果我们推断calculate()
方法从单例本身的状态获取其输入,那么至少方法的一部分(或它调用的方法)必须在检索该状态时同步。但是,这并不意味着必须同步整个方法调用。 calculate
方法需要锁定共享数据的时间比例将决定您实际可以获得多少并行...
更新数据库还需要某种同步。但是,这应该由JDBC连接对象和从中获取的对象来处理... 提供您遵守规则并且不尝试在多个线程之间共享连接。 (数据库更新也会出现并发瓶颈......假设更新适用于同一个或多个数据库表。)
答案 3 :(得分:0)
这取决于你如何实现Singleton。如果您使用Synchronized关键字,那么他们将不会等待。 使用Singleton进行初步初始化。
这样的事情:
public final class Universe {
public static Universe getInstance() {
return fINSTANCE;
}
// PRIVATE //
/**
* Single instance created upon class loading.
*/
private static final Universe fINSTANCE = new Universe();
/**
* Private constructor prevents construction outside this class.
*/
private Universe() {
//..elided
}
}
以上将在多线程环境中表现良好。或者你可以去实现Singleton的枚举。
检查此链接是否有各种单例实现:http://javarevisited.blogspot.in/2012/07/why-enum-singleton-are-better-in-java.html
答案 4 :(得分:0)
多个线程可以同时调用calculate()。
除非您执行某种类型的并发控制(使方法synchronized
是一个选项),否则这些调用不会在该JVM中排队(以串行方式执行)。
您的对象是单例的事实可能会也可能不会影响性能,具体取决于在compute()中如何使用该对象的属性(如果有)。
另外请记住,由于您正在“更新数据库”,因此表级或行级锁也可能会限制并发性。
如果你担心表现,最好的办法是测试它。