{"id":23550399,"url":"https://github.com/coralblocks/coralqueue","last_synced_at":"2025-07-21T13:34:57.753Z","repository":{"id":263869175,"uuid":"876804894","full_name":"coralblocks/CoralQueue","owner":"coralblocks","description":"CoralQueue is an ultra-low-latency, lock-free, garbage-free, batching and concurrent collection of circular data structures for inter-thread communication in Java.","archived":false,"fork":false,"pushed_at":"2025-07-05T02:21:39.000Z","size":1917,"stargazers_count":32,"open_issues_count":0,"forks_count":6,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-07-05T03:54:03.503Z","etag":null,"topics":["memory-barriers","queue","threads","volatile"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/coralblocks.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2024-10-22T15:27:02.000Z","updated_at":"2025-07-05T02:21:43.000Z","dependencies_parsed_at":"2025-01-16T16:45:38.853Z","dependency_job_id":"f5e11d50-a161-42de-8867-216c12d99779","html_url":"https://github.com/coralblocks/CoralQueue","commit_stats":{"total_commits":222,"total_committers":2,"mean_commits":111.0,"dds":"0.058558558558558516","last_synced_commit":"644907e0f8f4ff7d157ccce8f2bc22e4b930e4fa"},"previous_names":["coralblocks/coralqueue"],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/coralblocks/CoralQueue","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coralblocks%2FCoralQueue","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coralblocks%2FCoralQueue/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coralblocks%2FCoralQueue/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coralblocks%2FCoralQueue/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/coralblocks","download_url":"https://codeload.github.com/coralblocks/CoralQueue/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coralblocks%2FCoralQueue/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266312188,"owners_count":23909745,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-21T11:47:31.412Z","response_time":64,"last_error":null,"robots_txt_status":null,"robots_txt_updated_at":null,"robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["memory-barriers","queue","threads","volatile"],"created_at":"2024-12-26T10:16:06.674Z","updated_at":"2025-07-21T13:34:57.726Z","avatar_url":"https://github.com/coralblocks.png","language":"Java","readme":"# CoralQueue\nCoralQueue is an ultra-low-latency, lock-free, garbage-free, batching and concurrent collection of circular data structures for inter-thread communication in Java. It uses memory barriers through \u003ci\u003evolatile sequences\u003c/i\u003e instead of locks to allow Java threads (producers and consumers) to exchange messages as fast as possible. All data structures are circular and _bounded_, requiring producer/consumer _waiting_ (but not locking) when they are full/empty through a wait strategy or busy spinning.\n\nFor some performance numbers you can check [this link](https://www.coralblocks.com/index.php/coralqueue-performance-numbers/).\n\nThe data structures are: [Queue](#queue) (one-producer-to-one-consumer), [Multiplexer](#multiplexer) (many-producers-to-one-consumer), [Demultiplexer](#demultiplexer) (one-producer-to-many-consumers), [MpMc](#mpmc) (many-producers-to-many-consumers), [Broadcaster](#broadcaster) (one-producer-to-many-consumers), [MpMcBroadcaster](#mpmcbroadcaster) (many-producers-to-many-consumers), [Diamond](#diamond) (worker threads) and [RawQueue](#rawqueue) (binary raw).\n\n\u003cpre\u003e\n\u003cb\u003eNote:\u003c/b\u003e CoralQueue allows the exchange of messages \u003ci\u003einside the same JVM\u003c/i\u003e.\nFor a multicast message middleware solution to build distributed systems across multiple\nmachines using the \u003ci\u003esequencer architecture\u003c/i\u003e you should refer to \u003ca href=\"https://www.coralblocks.com/index.php/state-of-the-art-distributed-systems-with-coralmq/\"\u003ethis article\u003c/a\u003e.\n\u003c/pre\u003e\n\n## Queue\n\n\u003cimg src=\"images/Queue.png\" alt=\"Queue\" width=\"50%\" height=\"50%\" /\u003e\n\nThe Queue allows a single producer thread sending messages to the queue and a single consumer thread receiving messages from the queue, both running inside the same JVM. The consumer reads the messages (all the messages) in the same order that they were sent by the producer.\n\n- Click [here](src/main/java/com/coralblocks/coralqueue/example/queue/Minimal.java) for a minimal example of using the Queue\n- Click [here](src/main/java/com/coralblocks/coralqueue/example/queue/Basics.java) for a basic example of using the Queue\n\n\u003cdetails\u003e\n  \u003csummary\u003eClick here for all the details of how to use the Queue\u003c/summary\u003e\n  \n### All about using the Queue\n\nThe queue is a circular data structure with pre-allocated \u003ci\u003e data transfer mutable objects\u003c/i\u003e. You should see these data transfer mutable objects as \u003ci\u003ecarriers of data\u003c/i\u003e, in other words, they are there to allow\nyou to transfer \u003ci\u003edata\u003c/i\u003e (and not object references) from producers to consumers. The steps are:\n\n- A producer fetches an available data transfer mutable object from the queue\n- The producer populates the mutable object with the data it wants to transfer (i.e. send) to the consumer(s)\n- The producer flushes to notify the consumer(s)\n- A consumer fetches an available data transfer mutable object from the queue\n- The consumer reads the data from the mutable object\n- The consumer calls \u003ccode\u003edoneFetching()\u003c/code\u003e to notify the producer(s)\n\nBelow we use a \u003ccode\u003eStringBuilder\u003c/code\u003e as our data transfer mutable object to create an \u003ccode\u003eAtomicQueue\u003c/code\u003e:\n```Java\nfinal Queue\u003cStringBuilder\u003e queue = new AtomicQueue\u003cStringBuilder\u003e(StringBuilder.class); // default queue capacity is 1024\n```\n\nYou can also specify the capacity of the queue, which must be a power of two:\n```Java\nfinal Queue\u003cStringBuilder\u003e queue = new AtomicQueue\u003cStringBuilder\u003e(512, StringBuilder.class); // specifying the queue capacity\n```\nThe code above creates a queue with 512 pre-allocated StringBuilders. Note that it uses the default constructor of StringBuilder which by default creates a StringBuilder with size 16. That may be too small for our data transfer objects as we don’t want the StringBuilder resizing itself during runtime and creating garbage. So to create a bigger StringBuilder we can use a \u003ccode\u003ecom.coralblocks.coralqueue.util.Builder\u003c/code\u003e like below:\n```Java\nBuilder\u003cStringBuilder\u003e builder = new Builder\u003cStringBuilder\u003e() {\n    @Override\n    public StringBuilder newInstance() {\n        return new StringBuilder(1024);\n    }\n};\n```\n\nAnd pass this builder to the constructor of our \u003ccode\u003eAtomicQueue\u003c/code\u003e:\n```Java\nfinal Queue\u003cStringBuilder\u003e queue = new AtomicQueue\u003cStringBuilder\u003e(512, builder); // using a builder instead of the class\n```\n\n#### Sending messages to the queue\n\nTo send a message to the queue, you grab a data transfer mutable object from the queue, fill it with your data and call \u003ccode\u003eflush()\u003c/code\u003e as the code below illustrates:\n```Java\nStringBuilder sb;\nwhile((sb = queue.nextToDispatch()) == null); // busy spin...\nsb.setLength(0);\nsb.append(\"Hello there!\");\nqueue.flush();\n```\n\nNote that if the queue is full we just \u003ci\u003ebusy spin\u003c/i\u003e until a data transfer object becomes available. Later we will see how we can also use a \u003ccode\u003eWaitStrategy\u003c/code\u003e instead of busy spinning.\n\nYou can (and should) send messages in batches:\n```Java\nStringBuilder sb;\n \nwhile((sb = queue.nextToDispatch()) == null); // busy spin...\nsb.setLength(0);\nsb.append(\"Hello there!\");\n \nwhile((sb = queue.nextToDispatch()) == null); // busy spin...\nsb.setLength(0);\nsb.append(\"Hello again!\");\n \nqueue.flush();\n```\n\n#### Reading messages from the queue\n\nTo read messages from the queue you fetch them from a consumer thread, as the code below shows:\n```Java\nlong avail;\nwhile((avail = queue.availableToFetch()) == 0); // busy spin\nfor(int i = 0; i \u003c avail; i++) {\n    StringBuilder sb = queue.fetch();\n    // do whatever you want with the StringBuilder\n    // just do not create garbage\n    // copy char by char if needed\n    // or copy the contents to an external StringBuilder\n}\nqueue.doneFetching();\n```\nAgain we busy spin if the queue is empty. Later we will see how we can also use a \u003ccode\u003eWaitStrategy\u003c/code\u003e instead of busy spinning.\n\nNote that we fetch in batches, reducing the number of times we have to check for an empty queue through \u003ccode\u003eavailableToFetch()\u003c/code\u003e.\n\n\u003c/details\u003e \n\n\u003cdetails\u003e\n  \u003csummary\u003eClick here for all the details of how to use Wait Strategies\u003c/summary\u003e\n\n### All about using Wait Strategies\n\nBy default, you should busy-spin when the queue is full or empty. That’s usually the fastest approach but not always the best as you might want to allow other threads to use the CPU core. CoralQueue comes with a variety of wait strategies that you can use instead of busy spinning, and you can also create your own by implementing the \u003ccode\u003eWaitStrategy\u003c/code\u003e interface. Below are some examples of wait strategies that come with CoralQueue:\n\n- [ParkBackOffWaitStrategy](https://github.com/coralblocks/CoralQueue/blob/main/src/main/java/com/coralblocks/coralqueue/waitstrategy/ParkBackOffWaitStrategy.java): park (i.e. sleep) for 1 microsecond backing off up to a maximum of 1 millisecond in steps of 1 microsecond. The start, max and step values can be configured.\n- [BusySpinParkBackOffWaitStrategy](https://github.com/coralblocks/CoralQueue/blob/main/src/main/java/com/coralblocks/coralqueue/waitstrategy/BusySpinParkBackOffWaitStrategy.java): first busy spins for 10,000,000 cycles then it starts to park (i.e. sleep) by using the ParkBackOffWaitStrategy above. This is an example of a composite wait strategy, which combines multiple wait stratgies in a single one. The number of busy-spin cycles can be configured.\n- [BusySpinYieldSleepWaitStrategy](https://github.com/coralblocks/CoralQueue/blob/main/src/main/java/com/coralblocks/coralqueue/waitstrategy/BusySpinYieldSleepWaitStrategy.java): busy spins for 10,000,000 cycles, yields for 100 cycles then starts to sleep for 1 millisecond. All previous values can be changed/configured.\n\nTo use a wait strategy, all you have to do is call its \u003ccode\u003eawait()\u003c/code\u003e and \u003ccode\u003ereset()\u003c/code\u003e methods instead of busy spinning:\n\n#### Producer using a Wait Strategy\n```Java\nWaitStrategy producerWaitStrategy = new ParkWaitStrategy();\nStringBuilder sb;\nwhile((sb = queue.nextToDispatch()) == null) {\n    producerWaitStrategy.await(); // \u003c=====\n}\nproducerWaitStrategy.reset(); // \u003c=====\nsb.setLength(0);\nsb.append(\"Hello there!\");\nqueue.flush();\n```\n\n#### Consumer using a Wait Strategy\n```Java\nWaitStrategy consumerWaitStrategy = new BusySpinYieldSleepWaitStrategy();\nlong avail;\nwhile((avail = queue.availableToFetch()) == 0) {\n    consumerWaitStrategy.await(); // \u003c=====\n}\nconsumerWaitStrategy.reset(); // \u003c=====\nfor(int i = 0; i \u003c avail; i++) {\n    StringBuilder sb = queue.fetch();\n    // do whatever you want with the StringBuilder\n    // just do not create garbage\n    // copy char by char if needed\n    // or copy the contents to an external StringBuilder\n}\nqueue.doneFetching();\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eClick here for all the details of how to use Semi-Volatile Writes\u003c/summary\u003e\n\n### All about using Semi-Volatile Writes (lazySet)\n\nTo squeeze every bit of performance out of CoralQueue, you can use \u003ci\u003esemi-volatile writes\u003c/i\u003e (equivalent to [VarHandle.setRelease](https://docs.oracle.com/en/java/javase/23/docs/api/java.base/java/lang/invoke/VarHandle.html#setRelease(java.lang.Object...))) when sending and receiving messages. Basically, a semi-volatile write is done through the \u003ccode\u003elazySet\u003c/code\u003e method from \u003ccode\u003ejava.util.concurrent.AtomicLong\u003c/code\u003e. It is a faster operation for the thread that’s modifying the variable at the expense of the thread that’s interested in knowing about updates in the variable. For example, if you want to minimize the latency in the producer, you should use lazySet. On the other hand, if you want to minimize the message transit time, you should not use lazySet so the consumer is notified as soon as possible about a new message in the queue.\n\nBy default, CoralQueue does not use \u003ccode\u003elazySet\u003c/code\u003e, in other words the other thread is notified immediately (or as soon as possible). But you can easily take control of that by using the methods below:\n```Java\n// producer notifying consumer(s)\nqueue.flush(); // no lazySet by default (notify the consumer thread immediately at the expense of the producer thread)\nqueue.flush(true); // use lazySet (take more time to notify the consumer thread in order not to introduce any latency to the producer thread)\n```\n```Java\n// consumer notifying producer(s)\nqueue.doneFetching(); // no lazySet by default (notify the producer thread immediately at the expense of the consumer thread)\nqueue.doneFetching(true); // use lazySet (take more time to notify the producer thread in order not to introduce any latency to the consumer thread)\n```\n\u003c/details\u003e\n  \n## Multiplexer\n\n\u003cimg src=\"images/Mux.png\" alt=\"Multiplexer\" width=\"50%\" height=\"50%\" /\u003e\n\nThe Multiplexer allows multiple producer threads sending messages to the multiplexer and a single consumer thread receiving messages (all the messages) from the multiplexer, all running inside the same JVM.\nThe order that the consumer will process the messages is of course undetermined due to the simultaneous producers.\n\n- Click [here](src/main/java/com/coralblocks/coralqueue/example/multiplexer/Minimal.java) for a minimal example of using the Multiplexer\n- Click [here](src/main/java/com/coralblocks/coralqueue/example/multiplexer/Basics.java) for a basic example of using the Multiplexer\n\n## Demultiplexer\n\n\u003cimg src=\"images/Demux.png\" alt=\"Demultiplexer\" width=\"50%\" height=\"50%\" /\u003e\n\nThe Demultiplexer allows a single producer thread sending messages to the demultiplexer and multiple consumer threads receiving messages from the demultiplexer, all running inside the same JVM. `Note that messages are not duplicated by the demultiplexer.` They are distributed among the consumer threads, in other words, a message is processed only once by one of the consumers. `Also note that the order that the consumers will process the messages is undetermined.`\n\n- Click [here](src/main/java/com/coralblocks/coralqueue/example/demultiplexer/Minimal.java) for a minimal example of using the Demultiplexer\n- Click [here](src/main/java/com/coralblocks/coralqueue/example/demultiplexer/Basics.java) for a basic example of using the Demultiplexer\n\n## MpMc\n\n\u003cimg src=\"images/MpMc.png\" alt=\"MpMc\" width=\"50%\" height=\"50%\" /\u003e\n\nThe MpMc (i.e. Multiple Producers / Multiple Consumers) allows multiple producer threads sending messages to the mpmc and multiple consumer threads receiving messages from the mpmc, all running inside the same JVM. `Note that messages are not duplicated by the mpmc.` They are distributed among the consumer threads, in other words, a message is processed only once by one of the consumers. `Also note that the order that the consumers will process the messages is of course undetermined.`\n\n- Click [here](src/main/java/com/coralblocks/coralqueue/example/mpmc/Minimal.java) for a minimal example of using the MpMc\n- Click [here](src/main/java/com/coralblocks/coralqueue/example/mpmc/Basics.java) for a basic example of using the MpMc\n\n## Broadcaster\n\n\u003cimg src=\"images/Broadcaster.png\" alt=\"Broadcaster\" width=\"50%\" height=\"50%\" /\u003e\n\nThe Broadcaster allows a single producer thread sending messages to the broadcaster and multiple consumer threads receiving messages from the broadcaster, all running inside the same JVM. `Note that all consumers receive all messages.` `The consumer threads read the messages in the same order that they were sent by the single producer.`\n\n- Click [here](src/main/java/com/coralblocks/coralqueue/example/broadcaster/Minimal.java) for a minimal example of using the Broadcaster\n- Click [here](src/main/java/com/coralblocks/coralqueue/example/broadcaster/Basics.java) for a basic example of using the Broadcaster\n\n## MpMcBroadcaster\n\n\u003cimg src=\"images/MpMcBroadcaster.png\" alt=\"MpMcBroadcaster\" width=\"50%\" height=\"50%\" /\u003e\n\nThe MpMcBroadcaster (i.e. Multiple Producers / Multiple Consumers) allows multiple producer threads sending messages to the mpmc broadcaster and multiple consumer threads receiving messages from the mpmc broadcaster, all running inside the same JVM. `Note that all consumers receive all messages.` `Also note that the order that the consumers will process the messages is of course undetermined due to the simultaneous producers.`\n\n- Click [here](src/main/java/com/coralblocks/coralqueue/example/mpmcbroadcaster/Minimal.java) for a minimal example of using the MpMcBroadcaster\n- Click [here](src/main/java/com/coralblocks/coralqueue/example/mpmcbroadcaster/Basics.java) for a basic example of using the MpMcBroadcaster\n\n## Diamond\n\n\u003cimg src=\"images/Diamond.png\" alt=\"Diamond\" width=\"50%\" height=\"50%\" /\u003e\n\nThe Diamond allows tasks to be distributed across a set of _worker threads_ for execution. A producer thread will dispatch _tasks_ to the worker threads of the diamond and a consumer thread will fetch _executed_ tasks from the worker threads of the diamond. `It is not uncommon for the producer and consumer to be running on the same thread.` If order is important, in other words, if some tasks must be executed in order, they can be assigned to the same worker thread when the producer dispatches them.\n\n- Click [here](src/main/java/com/coralblocks/coralqueue/example/diamond/Minimal.java) for a minimal example of using the Diamond\n- Click [here](src/main/java/com/coralblocks/coralqueue/example/diamond/Basics.java) for a basic example of using the Diamond\n\n## RawQueue\n\nFor maximum performance (lowest possible latency) you can use the [RawQueue](src/main/java/com/coralblocks/coralqueue/raw/RawQueue.java) for a circular buffer of _raw bytes_. Therefore, instead of writing to mutable transfer objects from the queue, you write raw data (raw bytes) directly to a contiguous piece of circular memory, reducing the amount of pointer dereferencing and improving CPU cache locality by avoiding heap-scattered object references. The [RawBytes](src/main/java/com/coralblocks/coralqueue/raw/RawBytes.java) interface is implemented using a regular `ByteBuffer` to represent a contiguous circular memory that can be direct (off-heap) or non-direct (heap-based).\n\n- Click [here](src/main/java/com/coralblocks/coralqueue/example/raw/Minimal.java) for a minimal example of using the RawQueue\n- Click [here](src/main/java/com/coralblocks/coralqueue/example/raw/Basics.java) for a basic example of using the RawQueue\n\n## CoralRing\n\n\u003cimg src=\"images/OffHeapQueue2.png\" alt=\"CoralRing\" width=\"50%\" height=\"50%\" /\u003e\n\nCoralQueue is great for threads inside the same JVM. But what about threads running in _different JVMs_? For that you can check our [CoralRing](https://github.com/coralblocks/CoralRing) project which is an inter-process communication (IPC) shared-memory ring with waiting and non-waiting producers and consumers.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcoralblocks%2Fcoralqueue","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcoralblocks%2Fcoralqueue","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcoralblocks%2Fcoralqueue/lists"}