Java 弹簧DI的螺纹安全含义

Java 弹簧DI的螺纹安全含义,java,spring,dependency-injection,thread-safety,Java,Spring,Dependency Injection,Thread Safety,在我设计的示例中,团队成员列表对线程安全有什么影响 我能否依靠run()方法看到的列表状态保持一致 假定 spring在创建ATeamEpisodebean时只调用一次setATeamMembers方法 init方法由spring(init方法)在#1之后调用 ATeamMember类是不可变的 我是否需要声明团队成员易失性或类似情况 这种方法还有其他我所担心的可怕问题吗 俯瞰 如果这是明显的,或rtfm明显失败,则表示歉意 谢谢和问候 package-aTeam; 导入java.util

在我设计的示例中,团队成员列表对线程安全有什么影响

我能否依靠
run()
方法看到的列表状态保持一致

假定

  • spring在创建
    ATeamEpisode
    bean时只调用一次
    setATeamMembers
    方法

  • init
    方法由spring(init方法)在#1之后调用

  • ATeamMember
    类是不可变的

    • 我是否需要声明
      团队成员
      易失性
      或类似情况

    • 这种方法还有其他我所担心的可怕问题吗 俯瞰

  • 如果这是明显的,或rtfm明显失败,则表示歉意

    谢谢和问候

    package-aTeam;
    导入java.util.ArrayList;
    导入java.util.List;
    导入java.util.Random;
    公共类ATeamEpisode实现可运行{
    私人名单小组成员;
    /*春之地*/
    public void setATeamMembers(列出团队成员){
    this.teamMembers=newarraylist(teamMembers);
    }
    私有线程冲突线程;
    公共同步的void init(){
    System.out.println(“开始小冲突”);
    破坏();
    (小冲突线程=新线程(此为“小冲突线程”)).start();
    }
    公共同步的void destroy(){
    if(小冲突线程!=null){
    小冲突线程中断();
    小冲突线程=null;
    }
    }
    私人无效消防队(ATeamMember团队成员){
    System.out.println(teamMember.getName()+“喷洒天空…”);
    }
    @凌驾
    公开募捐{
    试一试{
    随机rnd=新随机();
    而(!Thread.interrupted()){
    fireswildlyintheair(teamMembers.get(rnd.nextInt(teamMembers.size()));
    线程睡眠(1000*rnd.nextInt(5));
    }
    }捕捉(中断异常e){
    System.out.println(“冲突结束”);
    /*按照亚当的建议编辑*/
    //Thread.currentThread().interrupt();
    }
    }
    }
    
    如您所说,如果setATeamMembers只被调用一次,并且您的代码中没有任何其他部分可以替代此集合,那么将其变为易失性是没有意义的。Volatile表示成员可以由不同的线程写入

    <> P>考虑到您的代码中没有一部分似乎正在更新此集合,您可能需要考虑使集合显式不可修改,例如使用CytRun.UnMudiFabelEistIn()。这向您和其他人表明,此集合不会被修改,并且如果您尝试无论如何修改它,将在您的脸上抛出一个巨大的异常


    Spring的惰性初始化是线程安全的

    也许吧。
    列表
    接口本身不是线程安全的,无论您做什么,它都无法在用户端实现线程安全

    您需要做的是创建一个线程安全列表(Java运行时有两个实现),并将其中一个用于
    teamMembers
    bean

    通过
    teamMembers
    字段访问bean不是问题,因为其他线程不创建新实例,而是更改
    teamMembers
    bean的状态(即内部数据)

    因此bean必须确保对其内部结构的更改正确同步

    在您的情况下,您将需要一个特殊的列表实现,它从列表中返回一个随机元素。为什么?因为调用
    teamMembers.get()
    时,
    teamMembers.size()
    的值可能已更改

    实现这一点的一个简单方法是将所有方法调用包装在此代码中:

     synchronized(teamMembers) { ... }
    

    但你必须确定你真的抓住了他们。实现这一点最简单的方法是,正如我上面所说的,编写自己的列表,其中提供了您需要的所有特殊方法。这样,您可以根据需要在方法内部使用锁或
    synchronized

    谁执行Runnable?谁打断了?通常,基于setter的注入遵循构造,因此我认为run()在这里是安全的。但是您的代码还有其他问题。例如,在线程被中断后调用Thread.currentThread().interrupt()。感谢Adam,有趣的一点,cf。在这里吞下异常可以吗?在从run()调用的子例程中,这是有意义的,它不能抛出checked InterruptedException,但不能直接在run()中抛出线程(runnable)应该存在的位置,因为您只想退出,所以他的代码没有任何部分会更新列表,所以这实际上不是问题,除非我们假设代码片段缺失。如果列表被更新,那么是的,呼叫应该被同步。@marb:最终,他将开始更新列表,然后,他将忘记在哪里使用了他应该用锁保护的呼叫。因此,最好确保他同步过多,直到他开始了解自己在做什么。