在java中使用DTO对象时的线程安全性

时间:2012-05-08 02:16:31

标签: java multithreading thread-safety

我的课程中有类似下面的代码,就像我的'Task'类一样。我将创建此类的多个实例并将其传递给threadpool

class Task {

    public void doJob() {

        String s = informationDto.getName();

    }
}

DTO:

class InformationDto{

    private String name;

    public getName(){}

    public setName(String n){}

}

我想知道informationDto.getName();声明。它会在多线程环境中返回正确的名称吗?

如果getName()方法是静态的,会发生什么?

我想为我正在创建的每个informationDto类使用Task。什么是最好的方法呢?

1)我想为每个InformationDto课程保留一个Task。 2)因为实例变量不是线程安全的我想知道我是否访问getName()方法(因为name是一个实例变量)我会得到我在Task类中设置的正确名称? 3)就像我在Task类中使用util类一样,它是否是线程安全的?如果不是,我怎么能以线程安全的方式使用某种util实例?

1 个答案:

答案 0 :(得分:4)

我仍然不太清楚你的问题,但在评论中说得足够,会尽力给你一个答案。

我认为getName()会这样做:

public getName() {
    return name;
}

setName()执行此操作:

public setName(String name) {
    this.name = name;
}

其中name是:

private String name;

多个线程使用此类的实例并不能保证每个人在询问getName()时都会看到相同的内容,直到确保没有人在其他人上调用setName()时正在努力。

保证getName()返回一致且相同值的一种方法是将其锁定。您可以通过使对象不可变来实现:

private final name;

public InformationDTO(String name) {
  this.name = name;
}

这样name保证不会更改,您可以安全地将对象传递给任意数量的线程,因为您知道没有人可以更改它。然而,这将使它不是一个完美的POJO,你不能设置该属性。如果您需要能够使用setName()(通过某种框架直接或间接),那么这将无法为您完成。

在多线程环境中,此实例还有什么问题?不多。 getName()不会返回部分状态,例如旧值的一半和另一个线程写入的新值的一半。你在那里安全。使getName()静态变化不大。现在它将是一个类方法,而不是一个实例方法,name也变成static,这是一个非常全球化的状态,你不需要在你的后院。

希望这能回答你的问题,或者至少为你提供足够的线索来确定你的下一步。

<强>更新即可。就像在评论中指出的那样,如果您希望name更改并希望确保所有线程都读取最新值,则可以在声明成员变量时使用volatile

private volatile String name;

使用volatile将确保your threads "communicate" on modification events and don't trust their local caches