在我设计的例子中,关于团队成员列表的线程安全有什么影响?
我可以依赖run()
方法看到的列表状态来保持一致吗?
假设
setATeamMembers
方法只在春天创建ATeamEpisode
bean时调用
#{
init
方法被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();
}
}
}
答案 0 :(得分:5)
如果正如你所说的那样,setATeamMembers只被调用一次,并且代码的其他部分都没有替换这个集合,那么就没有必要让它变得不稳定。易失性表示成员可以被不同的线程书面。
考虑到您的代码的任何部分似乎都没有更新此集合,您可能需要考虑使集合显式不可修改,例如通过使用Collections.unmodifiableList()。这让你和其他人清楚地知道,这个集合不会被修改,如果你试图修改它就会在你的脸上抛出一个很大的例外。
Spring的懒惰初始化是,AFAIR,线程安全。
答案 1 :(得分:3)
也许。这样的List
接口不是线程安全的,无论你做什么,它都不能在消费者端使用 。
您需要做的是创建一个线程安全列表(Java运行时有几个实现)并使用其中一个用于teamMembers
bean。
通过字段teamMembers
访问bean不是问题,因为其他线程不创建新实例,它们会更改状态(即内部的数据) teamMembers
bean。
因此bean必须确保对内部结构的更改正确同步。
在您的情况下,您将需要一个特殊的列表实现,它从列表中返回一个随机元素。为什么?因为调用teamMembers.size()
时teamMembers.get()
的值可能已更改。
实现此目的的一种简单方法是在此代码中包装所有方法调用:
synchronized(teamMembers) { ... }
但你必须确定你真的抓住了所有这些。实现这一目标的最简单方法是,如上所述,编写自己的列表,提供您需要的所有特殊方法。这样,您可以根据需要在方法内部使用锁或synchronized
。