我应该何时在多个线程中使用不同的实例或共享实例?

时间:2018-06-06 14:55:37

标签: java multithreading

第一种方式是:

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类对象并将它们分别传递给t1t2。在第二种情况下,我将同一个Apple类对象传递给t1t2。多线程方面的真正区别是什么?你能建议我哪种方式正确并推荐?谢谢!

4 个答案:

答案 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

在这个简单的例子中,这不是一个大问题。但是当处理其他任务(可能修改文件,访问数据库或任何依赖于确定性行为的任务)时,您将遇到大麻烦。