Spring DI的线程安全影响

use*_*948 8 java spring dependency-injection thread-safety

在我惯用的例子中,对于团队成员列表的线程安全有什么影响?

我可以依赖run()方法所看到的列表状态来保持一致吗?

假设

  1. setATeamMembers方法仅在创建ATeamEpisodebean 时由spring调用一次

  2. init方法在#1之后由spring(init-method)调用

  3. 这个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)

Nim*_*Nim 5

如果,正如你所说的那样,setATeamMembers只被调用一次,并且代码的其他任何部分都没有替换这个集合,那么就没有必要使它变得不稳定.易失性表示成员可以由不同的线程写入.

考虑到您的代码中没有任何部分似乎也在更新此集合,您可能需要考虑使集合显式不可修改,例如使用Collections.unmodifiableList().这让你和其他人清楚地知道这个集合不会被修改,并且如果你试图修改它就会在你的脸上抛出一个很大的例外.

Spring的懒惰初始化是AFAIR,线程安全.