使用ExecutorService存储线程特定变量的正确方式
多用户收件箱监听的线程变量存储方案
背景
我开发了一个连接多用户收件箱的应用,为避免轮询新消息,采用IMAP IDLE命令和消息计数监听器监听新消息。由于imap.idle()会阻塞当前线程,因此为每个用户单独创建线程并使其进入阻塞状态。
现有代码实现
线程池与任务存储
this.mailboxExecutor = Executors.newCachedThreadPool(); ConcurrentHashMap<Long, Future<?>> mailboxFutures = new ConcurrentHashMap<>();
启动用户收件箱监听线程
private void startMailboxListenerForUser(User user) { Future<?> future = mailboxExecutor.submit( () -> { Thread.currentThread().setName("MailboxService-User-" + user.getId()); LOG.debug("Started new thread: {}", Thread.currentThread().getName()); mailboxConnectionHandler.listenToMailbox(user); }); mailboxFutures.put(user.getId(), future); }
MailboxConnectionHandler类核心方法
void listenToMailbox(User user) throws MessagingException { Settings settings = user.getSettings(); Properties properties = getProperties(settings); Store store = createStoreSession(properties, user); IMAPFolder inbox = openInbox(store); addMessageCountListener(inbox, user); LOG.debug("Issuing IMAP idle command for mailbox of user {}.", user.getId()); inbox.idle(); }
我的思考
查阅相关资料后,我了解到需要关闭用户收件箱来终止IDLE命令,因此必须存储每个用户的IMAPFolder inbox实例。
我曾考虑用private static final ThreadLocal<IMAPFolder> inboxThreadLocal = new ThreadLocal<>();来存储,但因为使用了线程池(ExecutorService),线程会被复用,担心线程会错误地使用旧的inbox实例,所以认为这种方式不安全。
我的问题
在上述使用ExecutorService的场景中,存储线程特定变量的正确方式是什么?
我想到的一种方案是使用以用户ID为键的ConcurrentHashMap<Long, IMAPFolder>。
内容的提问来源于stack exchange,提问作者GeekChap
相关产品推荐
相关产品推荐

