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对象的位置就无关紧要了。请记住:实际上,您的对象确实需要“上下文”。如果您只需创建一个“局部变量”,而没有其他人可以访问它,那就太好了。但你很快就会发现,这将在其他方面限制你。所以,在当地“创造一切”是一项很好的政策,但你并不总能实现它!