docs: Add QuickFIX/J threading model documentation#1171
Draft
docs: Add QuickFIX/J threading model documentation#1171
Conversation
Co-authored-by: chrjohn <6644028+chrjohn@users.noreply.github.com> Agent-Logs-Url: https://github.com/quickfix-j/quickfixj/sessions/e6f7a3f4-396a-403d-b91a-6501d8d500db
Copilot
AI
changed the title
[WIP] Add documentation for QuickFIX/J threading model
docs: Add QuickFIX/J threading model documentation
Mar 21, 2026
chrjohn
reviewed
Mar 21, 2026
Member
|
@copilot please add a reference to the docs to README.MD |
Co-authored-by: chrjohn <6644028+chrjohn@users.noreply.github.com> Agent-Logs-Url: https://github.com/quickfix-j/quickfixj/sessions/22db1795-4f49-4956-b106-99eb3fef8630
Contributor
Author
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Documents the QFJ threading model in detail — covering the two
EventHandlingStrategyimplementations, the always-present timer thread, their interaction, and thread-safety implications for application developers.New files
docs/threading-model.md— Markdown version for GitHub rendering; covers all threading concepts with ASCII diagrams and code snippets from actual sourcequickfixj-core/src/main/doc/usermanual/usage/threading.html— HTML version matching the existing usermanual style (application.htmlconventions: DOCTYPE,style.css, header/footer)Updated
quickfixj-core/src/main/doc/usermanual/index.html— Added "Threading Model" link after "Creating Your Application"README.md— Added## threading modelsection linking todocs/threading-model.mdTopics covered
SingleThreadedEventHandlingStrategy(shared queue, singleQFJ Message Processordaemon thread) vsThreadPerSessionEventHandlingStrategy(per-sessionQF/J Session dispatcher: <sessionID>threads)QFJ Timerthread (SessionConnector.SessionTimerTask) fires every 1 s and callsSession.next()on all sessions — orthogonal to which strategy is in useSession.next()(timer: heartbeats, logon, schedule) andSession.next(Message)(dispatchers: message processing)Executorinjection (setExecutor()) for virtual-thread or pool integrationApplicationimplementationOriginal prompt
Task
Add a new documentation page covering the QuickFIX/J threading model in detail. The documentation should be placed in
quickfixj-core/src/main/doc/usermanual/usage/asthreading.html(following the existing HTML docs pattern) and also as a Markdown filedocs/threading-model.mdfor GitHub rendering.Content Requirements
The documentation must cover the following topics precisely, based on the actual source code:
1. Overview
QFJ uses Apache MINA for non-blocking I/O. The threading model is controlled by the
EventHandlingStrategyinterface, with two concrete implementations:SingleThreadedEventHandlingStrategy— one thread for all sessions (SocketAcceptor,SocketInitiator)ThreadPerSessionEventHandlingStrategy— one thread per session (ThreadedSocketAcceptor,ThreadedSocketInitiator)Both are orthogonal to the timer thread, which is always present and always calls
Session.next()on a 1-second schedule.2. Connector classes and their strategy
SocketAcceptorSingleThreadedEventHandlingStrategyQFJ Message ProcessorSocketInitiatorSingleThreadedEventHandlingStrategyQFJ Message ProcessorThreadedSocketAcceptorThreadPerSessionEventHandlingStrategyQF/J Session dispatcher: <sessionID>ThreadedSocketInitiatorThreadPerSessionEventHandlingStrategyQF/J Session dispatcher: <sessionID>3. Single-threaded model (
SingleThreadedEventHandlingStrategy)Class:
quickfix.mina.SingleThreadedEventHandlingStrategySource:
quickfixj-core/src/main/java/quickfix/mina/SingleThreadedEventHandlingStrategy.javaBlockingQueue<SessionMessageEvent>holds events from all sessions.QFJ Message Processor(a daemon thread) drains the queue and callssession.next(message)for each event viaSessionMessageEvent.processMessage().blockInThread(), which creates aThreadAdapterwrapping theblock()loop.onMessage()wraps incoming messages into aSessionMessageEventand puts them on the shared queue.block()loop polls the queue with a timeout (THREAD_WAIT_FOR_MESSAGE_MS) so it can periodically check theisStoppedflag.getQueueSize(SessionID)method returns the total queue size (single queue for all sessions — there is no per-session view).Key point for application developers: Because all sessions share a single processing thread, a slow
fromApp()callback will delay processing for all other sessions.4. Thread-per-session model (
ThreadPerSessionEventHandlingStrategy)Class:
quickfix.mina.ThreadPerSessionEventHandlingStrategySource:
quickfixj-core/src/main/java/quickfix/mina/ThreadPerSessionEventHandlingStrategy.javaConcurrentHashMap<SessionID, MessageDispatchingThread>maps each session to its own dispatcher thread.onMessage()call for a given session, a newMessageDispatchingThreadis created and started viastartDispatcherThread().MessageDispatchingThreadhas its ownBlockingQueue<Message>(or watermark-tracked queue) and loops callingsession.next(message).QF/J Session dispatcher: <BeginString>:<SenderCompID>/<TargetCompID>Executorcan be customised viasetExecutor(). The default isDedicatedThreadExecutor, which creates a rawnew Thread(command, name).start().stopDispatcherThreads()enqueuesEND_OF_STREAMto every dispatcher, setsstopping=true, and waits (polling every 100 ms) until all dispatchers reportisStopped.dispatchersmap.Key point for application developers: Since each session has its own thread, a slow
fromApp()for one session does not block others. However, yourApplicationimplementation must be thread-safe.5. The Timer Thread and
Session.next()This is a critical part of the threading model that is orthogonal to the message-processing strategies above.
Class:
quickfix.mina.SessionConnectorSource:
quickfixj-core/src/main/java/quickfix/mina/SessionConnector.java5.1 The
QFJ TimerthreadA single
ScheduledExecutorService(a shared static instance using aQFTimerThreadFactory) runs aSessionTimerTaskat a fixed rate of every 1000 ms.The timer is started by
startSessionTimer():