【问题标题】:Is String a immutable class in JAVA, So how to use this feature is multi-Thread programing?String是JAVA中不可变的类,那么如何使用这个特性就是多线程编程呢?
【发布时间】:2017-03-26 08:38:16
【问题描述】:
public class Test {  
    public static String str = "abc";

    public static void main(String[] args) {
        System.out.println("before run" + str);
        for (int i = 0; i < 5; i++) {
            new Thread(new Runnable() {
                public void run() {
                    try {
                       Thread.sleep(100);
                  } catch (InterruptedException e) {;}

                    str =str +"1";
                }
            }).start();
        }
        System.out.println("after run" + str);
    }
}

我对不可变类 String 进行了测试,它是一个线程安全的类,所以我想我不必做同步的东西

但是当结果出现时让我感到震惊 “在 abc 之前”和“在 abc 之后”。

当我删除那些 Thread.sleep(100);结果变成了 “在 abc 之前”和“在 abc1111 之后”。

public static String str被修改了,为什么?

【问题讨论】:

  • 您不是在修改 string,而是在修改引用它的 variable。为什么要给你存货?
  • 我看不到您可以修改字符串的值(例如“运行前”)...确实可以更改变量的值...但它与类型无关不可变...
  • 你没有改变一个字符串(因为字符串是不可变的,这是不可能的)。您正在为静态变量分配一个新字符串。这与不变性和线程无关。只做String s = "a"; s = "b";的可能性。
  • 如果您想确保str 不会改变,您可以通过将其声明为final:public static final String str = "abc";

标签: java string multithreading thread-safety


【解决方案1】:

不变性意味着您不能更改对象的内容。使用可变对象(例如数组、ArrayList、Date),您可以更改该对象所包含的内容。但是使用字符串你不能这样做。您的示例显示了用对不同对象的引用替换对一个对象的引用。

要禁止这种替换,请将变量设为 final。

【讨论】:

  • 非常感谢大家,我误解了“不变性”的含义
【解决方案2】:

正如其他人所说,您可以修改像 String 这样的不可变对象,但您可以更改引用变量以指向不同的字符串,就像您正在做的那样。

您会看到输出的差异,因为当 sleep 方法被删除或注释掉一些线程时,5 个线程运行得足够快,以至于 str 变量引用被更新以指向连接的字符串。这就是原因,当您通过删除 sleep 方法运行该程序时,您可能会看到不同的输出,如下所示。

after abc1
after abc11
after abc1
after abc

但是,当 sleep 方法没有被移除时,你的主线程甚至在所有其他线程完成之前等待完成,这就是你看到的大部分“在 abc 之后”作为输出的方式,因为连接可能不会在主线程到达时发生最后一个打印语句。但是,如果您将睡眠时间减少到 5 毫秒,这样您可能会看到输出有时显示为“abc1 之后”。

所以,基本上输出取决于主线程到达最后一个打印语句的速度,这与字符串是否不可变无关

【讨论】:

    【解决方案3】:

    public static String str被修改了,为什么?

    它并没有修改同一个String对象,而是引用变量str在每次执行时指向不同的对象(在JVM维护的字符串常量池中)连接(+)操作,即现有的字符串对象将被丢弃。

    使用不变性,一旦创建就无法更改现有对象内容,这在线程安全方面非常有用,即,您不需要任何显式同步/锁定来保护对象跨多个线程写入/读取。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-08-24
      • 2018-12-30
      • 1970-01-01
      • 2012-05-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多