在我设计的示例中,关于 teamMembers 列表的线程安全有何影响?
我能否依赖 run()
方法看到的列表状态保持一致?
假设
setATeamMembers
方法仅在创建ATeamEpisode
bean 时由 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();
}
}
}
最佳答案
如果像您所说的那样,setATeamMembers 只被调用一次,并且您的代码中没有任何其他部分会替换此集合,那么就没有必要将其设置为 volatile 集合。 Volatile 表示一个成员可以被不同的线程写入。
考虑到您的代码似乎也没有更新此集合,您可能需要考虑使集合显式不可修改,例如使用 Collections.unmodifiableList()。这让你和其他人清楚地知道,这个集合不会被修改,如果你无论如何都试图修改它,将会在你面前抛出一个巨大的异常。
Spring 的惰性初始化是,AFAIR,线程安全的。
关于java - Spring DI 的线程安全影响,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12781095/