use*_*948 8 java spring dependency-injection thread-safety
在我惯用的例子中,对于团队成员列表的线程安全有什么影响?
我可以依赖run()方法所看到的列表状态来保持一致吗?
假设
该setATeamMembers方法仅在创建ATeamEpisodebean 时由spring调用一次
该init方法在#1之后由spring(init-method)调用
这个ATeamMember类是不可变的
我是否需要声明teamMembers volatile或类似?
我忽略了这种方法还有其他可怕的问题吗?
如果这很明显,或者rtfm明显失败,请道歉
感谢致敬
埃德
package aTeam;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class ATeamEpisode implements Runnable{
private List<ATeamMember> teamMembers;
/* DI by spring */
public void setATeamMembers(List<ATeamMember> teamMembers){
this.teamMembers = new ArrayList<ATeamMember>(teamMembers);
}
private Thread skirmishThread;
public synchronized void init(){
System.out.println("Starting skirmish");
destroy();
(skirmishThread = new Thread(this,"SkirmishThread")).start();
}
public synchronized void destroy(){
if (skirmishThread != null){
skirmishThread.interrupt();
skirmishThread=null;
}
}
private void firesWildlyIntoTheAir(ATeamMember teamMember){
System.out.println(teamMember.getName()+" sprays the sky..");
}
@Override
public void run() {
try {
Random rnd = new Random();
while(! Thread.interrupted()){
firesWildlyIntoTheAir(teamMembers.get(rnd.nextInt(teamMembers.size())));
Thread.sleep(1000 * rnd.nextInt(5));
}
} catch (InterruptedException e) {
System.out.println("End of skirmish");
/* edit as per Adam's suggestion */
// Thread.currentThread().interrupt();
}
}
}
Run Code Online (Sandbox Code Playgroud)
如果,正如你所说的那样,setATeamMembers只被调用一次,并且代码的其他任何部分都没有替换这个集合,那么就没有必要使它变得不稳定.易失性表示成员可以由不同的线程写入.
考虑到您的代码中没有任何部分似乎也在更新此集合,您可能需要考虑使集合显式不可修改,例如使用Collections.unmodifiableList().这让你和其他人清楚地知道这个集合不会被修改,并且如果你试图修改它就会在你的脸上抛出一个很大的例外.
Spring的懒惰初始化是AFAIR,线程安全.