Java 在映射中存储计时器实例是否安全?

Java 在映射中存储计时器实例是否安全?,java,jakarta-ee,timer,ejb,Java,Jakarta Ee,Timer,Ejb,假设我在应用程序中定义了很多计时器 @Startup @Singleton public class ScheduleManager { @Resource TimerService timerService; Map<Long, Timer> timerMap; @PostConstruct void init() { timerMap = new HashMap<>(); for (int

假设我在应用程序中定义了很多计时器

@Startup
@Singleton
public class ScheduleManager {

    @Resource
    TimerService timerService;

    Map<Long, Timer> timerMap;

    @PostConstruct
    void init() {
        timerMap = new HashMap<>();
        for (int i = 0; i < 10; i++) {
            TimerConfig tc = new TimerConfig("someEntityId", true);
            Timer timer = timerService.createSingleActionTimer(new Date(TimeUnit.DAYS.toMillis(i)), tc);
            timerMap.put((long) i, timer);
        }
    }

    public void cancelTimerById(long i) {
        Timer timer = timerMap.get(i);
        if(timer != null) {
            timerMap.remove(i); //release the reference from Map
            timer.cancel();
        }
    } 
}
但这对于每次取消来说都有点太多了

我关心的是在映射中保留SingleActionTimer(或其他定期计时器)的实例。(用于GC清理)


谢谢

是的,这是一个安全的解决方案我不理解您的担忧,但从这段代码来看,您可以使用一个大小为10的列表,其中列表上的索引等于计时器id,因为您的id似乎介于0到9之间。注意:不要使用变量名,如
i
,而是使用
timerId
。@SteveC Singleton会话bean默认使用容器管理的并发性,并在所有方法上使用写锁,因此,我不会添加
synchronized
,如果它存在,我会建议将其删除。@b邮件您完全正确-我忘记了感谢您的评论,我误读了@Resource TimerService上的api…它声明每个创建的计时器都绑定到注入TimerService的ejb bean。首先,我认为getTimers()将返回整个应用程序中定义的所有计时器,但事实并非如此。因此,本例中的答案是“安全的”,但是在调用timeout=>释放引用后,您必须从映射中删除实例
public void cancelTimerById(long i) {
        for(Timer timer : timerService.getTimers()) {
            if(Long.valueOf(timer.getInfo().toString()).equals(i)) {
                timer.cancel();
            }
        }
    }