* Die vorliegende Version wurde ausgiebig mit Chat GPT diskutiert.
* Das _asynchrone_ Queuing der Nachrichten ist nicht notwendig.
* Um das Ziel, die asynchrone Verarbeitung der Ergebnisse asynchron
umzusetzen, ohne dabei den IO-Thread der Producer-Instanz zu blockieren,
zu erreichen, genügt es, das `CompleteableFuture` für die Verarbeitung
des Ergebnisses _synchron_ über `CompletableFuture.completedFuture()`
zu erzeugen und erst die blockierende Weiterverarbeitung, über
`thenApplyAsync()` an einen anderen Thread zu delegieren!
* D.h. auch, dass die verwirrende zusätzliche Log-Meldung
"Scheduled queuing of message..." ganz entfallen kann und an deren
Stelle wieder unverändert das Logging erfolgt, das festhält, wie lange
der Aufruf von `send()` gedauert hat.
* Außerdem wird die `Semaphore` nicht mehr benötigt, da alle
Aufrufe von `send()` _synchron_ in dem Thread erfolgen, der die
`for`-Schleife abarbeitet.
D.h., wenn diese Schleife beendet wird, können nicht mehr wie bisher
noch nachträglich asynchron weitere Aufrufe von `send()` erfolgen, auf
die zuvor mit Hilfe der `Semapohre` gewartet werden musste, damit kein
Fehler entsteht, weil `send()` aufgerufen wird, nachdem `close` auf der
`Producer`-Instanz aufgerufen wurde.
* Insgesamt schrumpfen die Unterschiede zu der Implementierung, die den
`Callback` verwendet auch angenehm auf ein Minimum zurück.
* *Beachte:*
** In einer produktiven Anwendung, sollte der Aufruf von `send()`
in einen `try`/`catch`-Block eingefasst werden, um eine korrekte
Fehlerbehandlung der bereits synchron beim Aufruf von `send()` erfolgten
Aufrufe sicherzustellen!
** Dies gilt aber genauso für die Implementierung, die den `Callback`
verwendet, ist also der einfachen Vorführ-Implementierung geschuldet,
die bei jedem synchronen Fehler abbricht.
** Hier kommt lediglich dazu, dass zusätzlich eine `InterruptedException`,
die von dem blockierenden Aufruf von `Future.get()` ausgelöst werden
kann, das Programm beendent könnte.