首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在Java中动态创建异步消息队列

在Java中动态创建异步消息队列
EN

Stack Overflow用户
提问于 2009-10-29 15:32:29
回答 5查看 8.4K关注 0票数 7

我需要在Java中动态创建异步消息队列。我的用例是通过多个SMTP服务器发送电子邮件:我需要强制要求发送到同一SMTP服务器的电子邮件是按顺序处理的,但发送到不同SMTP服务器的电子邮件可以同时处理。我过去使用过JMS,但据我所知,它只允许在编译时创建队列,而我需要在运行时创建队列(每个SMTP服务器一个队列)。

我是不是遗漏了一些关于JMS的东西,或者有没有什么其他的工具/提案需要我去看看?

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2009-11-01 06:06:11

我同意Adam的观点,用例听起来像是JMS的开销。Java内置的功能足够:

代码语言:javascript
运行
复制
package de.mhaller;

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.HashMap;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingDeque;

import org.junit.Assert;
import org.junit.Test;

public class Mailer {

    @Test
    public void testMailer() throws Exception {
        ExecutorService executor = Executors.newCachedThreadPool();
        ArrayList<Mail> log = new ArrayList<Mail>();
        LinkedBlockingDeque<Mail> incoming = new LinkedBlockingDeque<Mail>();

        // TODO: Put mails to be sent into the incoming queue
        incoming.offer(new Mail("foo1@localhost", "localhost"));
        incoming.offer(new Mail("foo2@otherhost", "otherhost"));
        incoming.offer(new Mail("foo3@otherhost", "otherhost"));
        incoming.offer(new Mail("foo4@localhost", "localhost"));

        Map<Mailserver, Queue<Mail>> queues = new HashMap<Mailserver, Queue<Mail>>();
        while (!incoming.isEmpty()) {
            Mail mail = incoming.pollFirst();
            Mailserver mailserver = findMailserver(mail);
            if (!queues.containsKey(mailserver)) {
                ArrayDeque<Mail> serverQueue = new ArrayDeque<Mail>();
                queues.put(mailserver, serverQueue);
                executor.execute(new SendMail(mailserver, serverQueue));
            }
            Queue<Mail> slot = queues.get(mailserver);
            slot.offer(mail);
        }

        assertMailSentWithCorrectServer(log);
    }

    private void assertMailSentWithCorrectServer(ArrayList<Mail> log) {
        for (Mail mail : log) {
            if (!mail.server.equals(mail.sentBy.mailserver)) {
                Assert.fail("Mail sent by wrong server: " + mail);
            }
        }
    }

    private Mailserver findMailserver(Mail mail) {
        // TODO: Your lookup logic which server to use
        return new Mailserver(mail.server);
    }

    private static class Mail {
        String recipient;
        String server;
        SendMail sentBy;

        public Mail(String recipient, String server) {
            this.recipient = recipient;
            this.server = server;
        }

        @Override
        public String toString() {
            return "mail for " + recipient;
        }
    }

    public static class SendMail implements Runnable {

        private final Deque<Mail> queue;
        private final Mailserver mailserver;

        public SendMail(Mailserver mailserver, Deque<Mail> queue) {
            this.mailserver = mailserver;
            this.queue = queue;
        }

        @Override
        public void run() {
            while (!queue.isEmpty()) {
                Mail mail = queue.pollFirst();
                // TODO: Use SMTP to send the mail via mailserver
                System.out.println(this + " sent " + mail + " via " + mailserver);
                mail.sentBy = this;
            }
        }

    }

    public static class Mailserver {
        String hostname;

        public Mailserver(String hostname) {
            this.hostname = hostname;
        }

        @Override
        public String toString() {
            return hostname;
        }

        @Override
        public int hashCode() {
            return hostname.hashCode();
        }

        @Override
        public boolean equals(Object obj) {
            return hostname.equals(((Mailserver) obj).hostname);
        }

    }

}
票数 6
EN

Stack Overflow用户

发布于 2009-10-29 15:41:49

JMS本身作为一种规范,在这个问题上相当沉默。大多数实现都允许您这样做,只是不是通过JMS本身,而是使用自己的API。但是您不能将像MDB这样的形式挂接到动态队列中。相反,您需要管理自己的连接和监听程序。

票数 1
EN

Stack Overflow用户

发布于 2009-10-29 15:52:34

上一次我们在WebSphere环境中研究这个问题时,动态创建队列是非常困难/不可能的(我认为临时队列对您来说太短暂了)。尽管存在用于创建队列的API,但它们需要在之后重新启动服务器才能激活。然后是MDB的问题。

基于这样一句格言,所有问题都可以通过额外的间接级别来解决,即假设可用打印机的集合相对较小,那么一个肮脏的变通方法如何?

创建队列Printer01到Printer99 (或一些较小的数字)。有一个“数据库”,它将队列映射到真正的打印机。当出现打印机请求时,您可以添加到映射表中。您可能有一些MDB查看永远不会使用的队列的开销,但除非您潜在的打印机数量很大,否则您可能负担得起?

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1642122

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档