Я только что нашел , ZiYa производит некоторые действительно сексуальные диаграммы и является конкретными направляющими.
оборотные стороны, это использует Flash и если Вы не хотите, чтобы сайты связались со страницей XML/SWF, это стоит 50$ за сайт.
[я еще не выбрал его, но хотел бросить его там в случае, если люди хотят проголосовать за него]
Я согласен с Адамом, вариант использования звучит так, как будто JMS накладные расходы. Достаточно встроенной функциональности Java:
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);
}
}
}
Сам JMS как спецификация довольно умалчивает об этой проблеме. Большинство реализаций позволяют делать это, но не через сам JMS, а с помощью собственного API. Но вы не сможете подключить к динамической очереди что-то формальное, например MDB. Скорее вам нужно будет управлять своими собственными подключениями и слушателями.
В последний раз, когда мы рассматривали это в среде WebSphere, было на удивление сложно / невозможно создавать очереди динамически (временные очереди, я думаю, для вас слишком временны). Хотя API-интерфейсы для создания очередей существовали, они требовали перезапуска сервера впоследствии, чтобы стать активными. Затем упоминается проблема MDB.
Как насчет грязного обходного пути, основанного на пословице, что все проблемы могут быть решены с помощью дополнительного уровня косвенного обращения, который предполагает, что набор доступных принтеров сравнительно невелик.
Создайте очереди от Printer01 до Printer99 (или какое-то меньшее число). Имейте «базу данных», которая сопоставляет очереди с реальными принтерами. По мере поступления запросов на принтеры вы можете добавлять их в таблицу сопоставления. У вас могут быть некоторые накладные расходы на MDB, просматривающие очереди, которые никогда не будут использоваться,
Редактировать: Упс, упустил простую вещь из-за глупости. Это решение неверно, хотя я сохраняю его здесь, поскольку оно все еще является средним (n + log (n)). Спасибо ShreevatsaR за указание на мою глупость. Я рассматривал поиск по дереву, но совершенно упустил идею поиска с возвратом второго по величине числа в log (n).
В любом случае, здесь следует мое доказательство того, почему низший алгоритм не больше, чем avg (n + log ( п)). В реальной жизни он должен, по крайней мере, работать довольно хорошо.
Чтобы доказать, что это среднее число. n + log n, нам просто нужно доказать, что первое сравнение в среднем выполняется только log (n) раз.
Я проделал это с помощью activemq - я фактически разместил вопрос по этому поводу в то время, так как у меня были аналогичные проблемы (документация JMS в то время говорила, что это не поддерживается) и было заверил, что его поддержали.