我正在编写一个静态实用程序方法。我知道方法 isEmpty()
和 isNew()
是线程安全的。在 getTotal(...)
方法中,我使用 StringBuilder
作为参数以及 String 和 int。 StringBuilder
是可变的。 getTotal()
是线程安全的吗?如果是这样,请解释为什么即使 StringBuilder 是可变的。我不确定 getCharge()
是否是线程安全的,因为它正在调用方法 getTotal()
。有人可以判断它是否是线程安全的吗?
public class NewStringUtils {
public static boolean isEmpty(String s){
return (s == null || s.trim().length()==0);
}
public static boolean isNew(String code){
return( "1009".equals(code) || "1008".equals(code) );
}
//StringBuilder is mutable -- is the below method threadsafe
public static int getTotal(StringBuilder sb,String oldCode ,int a, int b){
//Is it Threadsafe or not .If so just bcz every thread invoking this method will have its own copy and other threads can't see its value ??
int k =0;
if("1011".equals(oldCode) && "1021".equals(sb.toString()) {
k = a+b;
}
return k;
}
// is the below method threadsafe
public static int getCharge(String code,String oldCode,int charge1,int charge2){
int total =0;
StringBuilder sb = new StringBuilder("1021");
if(!NewStringUtils.isEmpty(code)){
if(NewStringUtils.isNew(code)){
//here invoking a static method which has StringBuilder(Mutable) as a parameter
total = NewStringUtils.getTotal(sb,oldCode,charge1,charge2);
}
}
return total;
}
}
最佳答案
getTotal
不是 thread-safe
因为有可能两个或两个以上的 threads
正在传递相同的 StringBuilder 引用
到 getTotal
方法作为参数并在传递之前修改 StringBuilder
...
而且您的 getCharge
是完全线程安全的,因为这里每个 thread
都在自己的 stack
中制作 StringBuilder
对象的本地副本>。所以不用担心 getCharge
的线程安全。
这是一个简短的演示,它演示了为什么 getTotal
不是 ThreadSafe:
class ThreadSafe
{
public static int getTotal(StringBuilder sb,String oldCode ,int a, int b)
{
int k =0;
try
{
System.out.println(Thread.currentThread().getName() + " have sb as " + sb);
Thread.sleep(100);//Added intentionally to show why it is not thread safe.
}
catch (Exception ex)
{
System.out.println(ex);
}
if("1011".equals(oldCode) && "1021".equals(sb.toString()))
{
System.out.println(Thread.currentThread().getName()+" is within if loop");//Thread1 should be within this if block but it's not.
k = a+b;
}
return k;
}
public static void main(String[] args)
{
final StringBuilder sBuilder = new StringBuilder();
Thread th1 = new Thread(new Runnable()
{
public void run()
{
sBuilder.append("1021");
getTotal(sBuilder,"1011",10,20);
}
},"Thread1");
Thread th2 = new Thread(new Runnable()
{
public void run()
{
sBuilder.append("22");
getTotal(sBuilder,"1011",10,20);
}
},"Thread2");
th1.start();
th2.start();
}
}
在我的系统中,输出是:
Thread1 have sb as 1021
Thread2 have sb as 102122
假设 Thread1
在 Thread2
之前开始,这确实发生在这里(如输出所示),如果 getTotal
将是 thread -safe
那么,语句Thread1 is within if loop 必须已经打印在输出中。但事实并非如此。 WHY? 因为在 Thread1
(with sb = "1021") 在 getTotal
方法中进入休眠状态后,线程被 Thread2
。 Thread2
将 22
附加到现有的 StringBuilder
对象 sBuilder
(即现在的新值是 102122
)。同样,当 Thread2
调用 sleep 方法时,它被 Thread1
抢占。 Thread1
转到 if
构造,但到现在 sBuilder
的内容已更改为 102122
。因此,如果 Thread1
的条件变为 false。如果我们认为 getTotal
是线程安全的,它不会打印出 Thread1 位于 if loop
中的那一行。因此证明 getTotal
不是线程安全的。
我们如何才能使 getTotal
线程安全?
- By passing
String
instead ofStringBuilder
.
关于java - java中的多线程静态方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15690445/