第一种方式是:
public class Demo {
public static void main (String args[]) {
Apple a1 = new Apple();
Apple a2 = new Apple();
Thread t1 = new Thread(a1, "First Thread");
Thread t2 = new Thread(a2, "Second Thread");
t1.start();
t2.start();
}
}
第二种方式是:
public class Demo {
public static void main (String args[]) {
Apple a = new Apple();
Thread t1 = new Thread(a, "First Thread");
Thread t2 = new Thread(a, "Second Thread");
t1.start();
t2.start();
}
}
void run()
方法在Apple类中,我没有将其粘贴到此处。
似乎在第一种情况下我创建了2个Apple类对象并将它们分别传递给t1
和t2
。在第二种情况下,我将同一个Apple类对象传递给t1
和t2
。多线程方面的真正区别是什么?你能建议我哪种方式正确并推荐?谢谢!
答案 0 :(得分:1)
如果您的Apple
对象是无状态的,那么没有区别。
但是如果它有一些状态并且其run()
方法修改了它的属性,那么你需要同步对Apple
对象的那些属性的访问(或确保这些属性是线程安全的)。
更喜欢什么取决于您的业务逻辑。
答案 1 :(得分:1)
如果Apple
是一个thread-safe的对象,那么在线程之间共享它可能是好的(或者确实可取)。如果它不是线程安全的,那么通过同时使用它,您将为race conditions和其他难以诊断的错误创建机会。
答案 2 :(得分:0)
差异很大程度上取决于Apple
类的实现,在一种情况下,这可能是最佳选择,而在另一种情况下,这可能是一个巨大的错误。
如果类Apple
是不可变的,并且如果它只具有仅依赖于它们的输入参数的纯函数,则只是更好地公开某些数据或事件,那么使用相同的实例是所希望的方法。
另一方面,如果没有使用多个线程的类,那么你肯定会遇到race condition个问题。
答案 3 :(得分:0)
这实际上取决于Apple
班级的真正作用。我们来看一个示例Apple
类:
public class Apple implements Runnable{
private int counter;
@Override
public void run(){
for(int i = 0; i < 10; i++){
counter += i;
}
System.out.println(counter);
}
}
现在,第一种方式是在控制台中获得如下所示的打印件:
45 // first thread
45 // second thread
虽然在第二种方式中它会非常难以预测,因为现在两个线程都在修改counter
变量。它最多看起来像这样:
45 // first thread
90 // second thread
但也可能看起来像这样:
51 // first thread
90 // second thread
在这个简单的例子中,这不是一个大问题。但是当处理其他任务(可能修改文件,访问数据库或任何依赖于确定性行为的任务)时,您将遇到大麻烦。