Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/386.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 多线程:将实例和局部变量传递给线程_Java_Multithreading_Thread Safety - Fatal编程技术网

Java 多线程:将实例和局部变量传递给线程

Java 多线程:将实例和局部变量传递给线程,java,multithreading,thread-safety,Java,Multithreading,Thread Safety,我对将实例和局部变量作为参数传递给线程持怀疑态度 让我给你举个简单的例子: public class Foo { private int num; private String str; public Foo(int num, String str){ this.num = num; this.str = str; } public int getNum() { return num; }

我对将实例和局部变量作为参数传递给线程持怀疑态度

让我给你举个简单的例子:

public class Foo {
    private int num;
    private String str;

    public Foo(int num, String str){
        this.num = num;
        this.str = str;
    }

    public int getNum() {
        return num;
    }

    public String getStr() {
        return str;
    }
}


public class FooRunnable implements Runnable {

    private Foo foo;

    public FooRunnable(Foo foo){
        this.foo = foo;
    }

    @Override
    public void run() {
        System.out.println("Number =" +foo.num);
        System.out.println("String =" +foo.str);    
    }
}

public class Test {

private Foo fooField;

public Test(){
    fooField = new Foo(4, "four");
}

public void launchField(){
    Thread th = new Thread(new FooRunnable(fooField));
    th.start();
}

public void launchLocalVariable(){
    Foo fooLocal = new Foo(5,  "five");
    Thread th = new Thread(new FooRunnable(fooLocal));
    th.start();
}

public static void main(String[] args) {
    Test test =  new Test();
    test.launchField();
    test.launchLocalVariable();
}
}

这只是一个启动两个线程的愚蠢程序:一个将实例变量作为参数传递给线程,另一个传递局部变量。稍后,两个线程都将传递的参数中的内容写入控制台


对于局部变量,我确信它的行为是线程安全的。在第二种情况下,我认为不会,因为可能会缓存该变量。你觉得怎么样?我错了吗

这很简单:如果信息可以被线程更改,那么您必须始终担心线程安全

重要的部分是:改变的能力

在您的示例中,Foo的字段是只读的。创建Foo对象后,无法更改它们。因此,任何Foo对象的使用都是线程安全的。即使你给10个不同的线程相同的Foo对象;他们将始终看到相同的数据

类的这个属性称为不变性;通过对Foo中的两个字段使用final关键字,可以使这一点更加明确。简单地说:如果您可以将所有类设计为不可变的,那么就不必担心线程安全


但是如果在Foo上有setter,使其他人能够在创建Foo对象时更改字段;那么“本地”和“字段”确实会产生不同。

这很简单:如果信息可以被线程更改,那么您必须始终担心线程安全

重要的部分是:改变的能力

在您的示例中,Foo的字段是只读的。创建Foo对象后,无法更改它们。因此,任何Foo对象的使用都是线程安全的。即使你给10个不同的线程相同的Foo对象;他们将始终看到相同的数据

类的这个属性称为不变性;通过对Foo中的两个字段使用final关键字,可以使这一点更加明确。简单地说:如果您可以将所有类设计为不可变的,那么就不必担心线程安全


但是如果在Foo上有setter,使其他人能够在创建Foo对象时更改字段;那么“本地”和“外地”确实会有所不同。

谢谢@Jägermeister,我理解。但是,在我为Foo类定义setter并使用它分配值的情况下,哪种情况是线程安全的?我认为“本地”样本是完全线程安全的,不是吗?我想我告诉过你需要知道什么。要点:如果任何其他线程能够更改对象,那么您就有一个潜在的问题。奇怪的例子:假设你的类Foo有静态字段。。。那么创建Foo对象的位置就无关紧要了。请记住:实际上,您的对象确实需要“上下文”。如果您只需创建一个“局部变量”,而没有其他人可以访问它,那就太好了。但你很快就会发现,这将在其他方面限制你。所以,在当地“创造一切”是一项很好的政策,但你并不总能实现它!谢谢@Jägermeister,我理解。但是,在我为Foo类定义setter并使用它分配值的情况下,哪种情况是线程安全的?我认为“本地”样本是完全线程安全的,不是吗?我想我告诉过你需要知道什么。要点:如果任何其他线程能够更改对象,那么您就有一个潜在的问题。奇怪的例子:假设你的类Foo有静态字段。。。那么创建Foo对象的位置就无关紧要了。请记住:实际上,您的对象确实需要“上下文”。如果您只需创建一个“局部变量”,而没有其他人可以访问它,那就太好了。但你很快就会发现,这将在其他方面限制你。所以,在当地“创造一切”是一项很好的政策,但你并不总能实现它!