java - java中的多线程静态方法

标签 java multithreading static static-methods

我正在编写一个静态实用程序方法。我知道方法 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

假设 Thread1Thread2 之前开始,这确实发生在这里(如输出所示),如果 getTotal 将是 thread -safe 那么,语句Thread1 is within if loop 必须已经打印在输出中。但事实并非如此。 WHY? 因为在 Thread1(with sb = "1021") 在 getTotal 方法中进入休眠状态后,线程被 Thread2Thread222 附加到现有的 StringBuilder 对象 sBuilder(即现在的新值是 102122)。同样,当 Thread2 调用 sleep 方法时,它被 Thread1 抢占。 Thread1 转到 if 构造,但到现在 sBuilder 的内容已更改为 102122。因此,如果 Thread1 的条件变为 false。如果我们认为 getTotal 是线程安全的,它不会打印出 Thread1 位于 if loop 中的那一行。因此证明 getTotal 不是线程安全的。

我们如何才能使 getTotal 线程安全?

  1. By passing String instead of StringBuilder.

关于java - java中的多线程静态方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15690445/

相关文章:

java - 将 Java 应用程序编写为 jar 和 apk

c# - 有序执行线程

multithreading - atomic.Load 和atomic.Store 的意义是什么

c++ - Qt moveToThread 和数据竞争

C++,静态与命名空间与单例

java - 如何在java中正确创建带有静态变量的配置类?

c++ - 程序退出期间的函数局部静态初始化

Java:无法实例化 Foo 类型

java - 在Java中实现多维度的Adaboost

java - 使用 SimpleXsdSchema 创建 DefaultWsdl11Definition