String在JAVA中是一个不可变的类,那么如何使用多线程编程这一特性呢? 公共类测试{ 公共静态字符串str=“abc”; 公共静态void main(字符串[]args){ System.out.println(“运行前”+str); 对于(int i=0;i

String在JAVA中是一个不可变的类,那么如何使用多线程编程这一特性呢? 公共类测试{ 公共静态字符串str=“abc”; 公共静态void main(字符串[]args){ System.out.println(“运行前”+str); 对于(int i=0;i,java,string,multithreading,thread-safety,Java,String,Multithreading,Thread Safety,我对immutable类String做了一个测试,它是一个线程安全的类,所以我想我不必做同步的事情 但当结果以令人震惊的方式出现时,我感到震惊 “abc之前”和“abc之后” 当我取下那些线的时候。睡眠(100);结果是 “abc之前”和“abc1111之后” 公共静态字符串str被修改了,为什么?不变性意味着您不能更改对象的内容。使用可变对象(如array、ArrayList、Date),可以更改该对象所包含的内容。但有了弦,你就不能这么做。您的示例显示了将对一个对象的引用替换为对另一个对象的

我对immutable类String做了一个测试,它是一个线程安全的类,所以我想我不必做同步的事情

但当结果以令人震惊的方式出现时,我感到震惊 “abc之前”和“abc之后”

当我取下那些线的时候。睡眠(100);结果是 “abc之前”和“abc1111之后”


公共静态字符串str被修改了,为什么?

不变性意味着您不能更改对象的内容。使用可变对象(如array、ArrayList、Date),可以更改该对象所包含的内容。但有了弦,你就不能这么做。您的示例显示了将对一个对象的引用替换为对另一个对象的引用

若不允许此替换,请将变量设为final

公共静态字符串str被修改了,为什么

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


有了不变性,一旦创建,就不能更改现有对象内容,这对于线程安全来说是很好的,也就是说,不需要任何显式同步/锁来跨多个线程写入/读取来保护对象。

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

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

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);
    }
}
但是,如果不删除sleep方法,则主线程等待甚至在所有其他线程完成之前就完成了,这就是您通常将“after abc”视为输出的方式,因为当主线程到达最后一个print语句时,连接可能不会发生。但是,如果您将睡眠时间减少到5毫秒,您可能会看到输出有时是“在abc1之后”


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

您不是在修改字符串,而是在修改引用它的变量。为什么会这样?我看不出你能修改字符串的值(比如“运行前”)。。。实际上,您可以更改变量的值。。。但这与类型是不可变的无关……您并没有改变字符串(因为字符串是不可变的,所以这是不可能的)。您正在为静态变量分配一个新字符串。这与不变性和线程无关。只允许执行
String s=“a”;s=“b”
。如果要确保
str
不会更改,可以通过将其声明为final:
public static final String str=“abc”。非常感谢各位,我误解了“不变性”的含义
after abc1
after abc11
after abc1
after abc