2013-05-10 86 views
0

我有一个服务类,它是一个接口的实现,它用Spring作为服务和单例进行了注释。我有两个不同的方法,每个方法创建一个字符串生成器局部变量。我有一个私有方法,它需要一个字符串构建器和一个字符串,并且这两个参数都是最终变量。此私有方法根​​据在其他字符串变量中找到的信息将信息附加到该字符串构建器。在每个实现的方法中,我都调用该私有方法传递本地创建的字符串构建器和必需的字符串。使用Java,这种类型的安装和线程安全方法调用吗?

我相信这两个实现的方法是线程安全的,但我不确定私有方法。那个字符串生成器线程是否安全?是否有参数作为最终的帮助?我认为最终是为了保证线程安全,但同时我认为最终意味着我不能追加任何东西。

这个stackoverflow问题和答案说,它不会是,但在例子中的参数不是最终的,但也许这并不重要。

Is that StringBuilder variable thread safe in this code?

这里是什么,我有一个例子:

@Service 
@Scope("singleton") 
public class SingletonService { 

    @Override 
    public String buildSelect(final Integer id){ 
     StringBuilder sb = new StringBuilder("select * from table "); 
     Map<String,Object> properties = new HashMap<String,Object>(); 
     addWhere(sb,properties,id); 
     return sb.toString(); 
    } 

    @Override 
    public String buildCount(final Integer id){ 
     StringBuilder sb = new StringBuilder("select count(id) from table "); 
     Map<String,Object> properties = new HashMap<String,Object>(); 
     addWhere(sb,properties,id); 
     return sb.toString(); 
    } 

    private void addWhere(final StringBuilder sb, final Map<String,Object> properties, final Integer id){ 
     if(id != null){ 
      sb.append("where id = :id); 
      properties.put("id",id); 
     } 
    } 
} 

回答

1

final具有比使它所以你不能意外分配的东西给变量其他方法签名中使用时,绝对没有任何影响在方法里面。

除此之外......为什么不会此代码是线程安全的?

您传递给您的公共方法的唯一方法是Integer,它是不可变的,并且没有任何其他方法是外部修改的。

所以是的,因为没有涉及并发,所以这是线程安全的。

这就是说,这也没有多大意义。你正在创建一个Map,放入一些东西,然后丢弃它。

+0

是的,看起来有点荒谬。这不是整个班级,只是一个简单的例子,我没有彻底移除地图部分。我比其他任何事情都更担心字符串的产生。感谢您的回答。关于变量的最后 - 我正在改变变量的值,但间接地通过它的追加方法 - 如果我试图给它分配一个新的字符串构建器实例,最终会发挥作用吗? – Elrond 2013-05-10 22:03:39

+0

@Elrond - 正确。 java中的'final'意味着你不能在初始赋值后重新赋值给变量;它与变量所持有的对象没有任何关系。你并没有改变变量的*值*,而是使用变量引用的对象。请参阅:http://stackoverflow.com/a/10340003/302916 – 2013-05-10 22:05:31

1

是的,这是线程安全的。

每个线程都有自己的堆栈存放变量。在这种情况下,该变量是一个引用,每个线程一个引用,由该线程创建的StringBuilder的实例。 StringBuilder的实例将在堆中创建,因此可以共享,但您必须显式传递线程之间的引用才能发生。