record Message(String type, String value) {} Map> mailboxes = new ConcurrentHashMap<>(); BlockingQueue mailbox(String name) { return mailboxes.computeIfAbsent( name, _ -> new LinkedBlockingQueue<>() ); } void listen(String mailboxName, Consumer receiver) { try { while (true) receiver.accept(mailbox(mailboxName).take()); } catch (InterruptedException _) { Thread.currentThread().interrupt(); } } String rot13(String text) { var result = new StringBuilder(); for (var character : text.toCharArray()) { if (character >= 'a' && character <= 'z') character = (char) ('a' + (character - 'a' + 13) % 26); else if (character >= 'A' && character <= 'Z') character = (char) ('A' + (character - 'A' + 13) % 26); result.append(character); } return result.toString(); } void runConsoleIn() { try { while (true) { var text = IO.readln(); if (text == null) return; mailbox("consoleIn.outbox") .put(new Message("TEXT", text)); } } catch (InterruptedException _) { Thread.currentThread().interrupt(); } } Map rot13Subscriptions = new HashMap<>(); Map consoleOutSubscriptions = new HashMap<>(); void subscribe( Map subscriptions, String mailboxName, Consumer receiver) { subscriptions.computeIfAbsent( mailboxName, name -> Thread.ofVirtual().start(() -> listen(name, receiver)) ); } void processWithRot13(Message message) { if (!message.type().equals("TEXT")) return; try { mailbox("rot13.outbox").put( new Message("TEXT", rot13(message.value())) ); } catch (InterruptedException _) { Thread.currentThread().interrupt(); } } void runRot13() { try { while (true) { var message = mailbox("rot13.inbox").take(); if (message.type().equals("TOPIC")) subscribe( rot13Subscriptions, message.value(), this::processWithRot13 ); else processWithRot13(message); } } catch (InterruptedException _) { Thread.currentThread().interrupt(); } } void print(Message message) { if (message.type().equals("TEXT")) IO.println(message.value()); } void runConsoleOut() { try { while (true) { var message = mailbox("consoleOut.inbox").take(); if (message.type().equals("TOPIC")) subscribe( consoleOutSubscriptions, message.value(), this::print ); else print(message); } } catch (InterruptedException _) { Thread.currentThread().interrupt(); } } void main() throws Exception { Thread.ofVirtual().start(this::runConsoleIn); Thread.ofVirtual().start(this::runRot13); Thread.ofVirtual().start(this::runConsoleOut); mailbox("rot13.inbox").put( new Message("TOPIC", "consoleIn.outbox") ); mailbox("consoleOut.inbox").put( new Message("TOPIC", "rot13.outbox") ); Thread.currentThread().join(); }