6
6
[ ![ javadoc] ( https://javadoc.io/badge2/com.softwaremill.jox/channels/javadoc.svg )] ( https://javadoc.io/doc/com.softwaremill.jox/channels )
7
7
8
8
Modern concurrency for Java 21 (backed by virtual threads, see [ Project Loom] ( https://openjdk.org/projects/loom/ ) ).
9
- Requires JDK 21.
10
9
Includes:
11
10
12
11
* Fast and Scalable Channels in Java. Inspired by the "Fast and Scalable Channels in Kotlin Coroutines"
13
12
[ paper] ( https://arxiv.org/abs/2211.04986 ) , and
14
13
the [ Kotlin implementation] ( https://github.com/Kotlin/kotlinx.coroutines/blob/master/kotlinx-coroutines-core/common/src/channels/BufferedChannel.kt ) .
15
14
* Programmer-friendly structured concurrency
16
- * Blocking, synchronous, functional streaming operators
15
+ * Blocking, synchronous, functional streaming
17
16
18
17
JavaDocs can be browsed
19
18
at [ https://javadoc.io ] ( https://www.javadoc.io/doc/com.softwaremill.jox/core/latest/com.softwaremill.jox/com/softwaremill/jox/package-summary.html ) .
@@ -35,7 +34,6 @@ For a Scala version, see the [Ox project](https://github.com/softwaremill/ox).
35
34
36
35
* [ Channels] ( #channels )
37
36
* [ Structured concurrency] ( #structured-concurrency )
38
- * [ Streaming] ( #streaming )
39
37
* [ Flows] ( #lazy-streaming---flows )
40
38
41
39
## Channels
@@ -343,6 +341,8 @@ ChainedKotlinBenchmark.channelChain_defaultDispatcher 16
343
341
344
342
## Structured concurrency
345
343
344
+ Requires the current LTS release of Java - JDK 21 (won't work with newer versions).
345
+
346
346
### Dependency
347
347
348
348
Maven:
@@ -431,17 +431,14 @@ so that it can be properly handled. Moreover, no detail is lost: all exceptions
431
431
suppressed exceptions.
432
432
433
433
As ` JoxScopeExecutionException ` is unchecked, we introduced utility method called
434
- ` JoxScopeExecutionException#unwrapAndThrow ` .
435
- If the wrapped exception is instance of any of passed classes, this method unwraps original exception and throws it as
436
- checked exception, ` throws ` signature forces exception handling.
437
- If the wrapped exception is not instance of any of passed classes, ** nothing happens** .
438
- All suppressed exceptions are rewritten from ` JoxScopeExecutionException `
434
+ ` JoxScopeExecutionException#unwrapAndThrow ` . If the wrapped exception is an instance of any of the passed classes, this
435
+ method unwraps original exception and throws it as checked exception; then the ` throws ` signature forces exception
436
+ handling. If the wrapped exception is not instance of any of the passed classes, ** nothing happens** . All suppressed
437
+ exceptions from ` JoxScopeExecutionException ` are added as suppressed to the unwrapped one.
439
438
440
439
** Note** ` throws ` signature points to the closest super class of passed arguments.
441
440
Method does ** not** rethrow ` JoxScopeExecutionException ` by default.
442
- So it is advised to manually rethrow it after calling ` unwrapAndThrow ` method.
443
-
444
- e.g.
441
+ So it is advised to manually rethrow it after calling ` unwrapAndThrow ` method, e.g.:
445
442
446
443
``` java
447
444
import com.softwaremill.jox.structured.JoxScopeExecutionException ;
@@ -651,10 +648,10 @@ The `FlowEmit` instance is used to emit elements by the flow, that is process th
651
648
pipeline. This method only completes once the element is fully processed, and it might throw exceptions in case there's
652
649
a processing error.
653
650
654
- As part of the callback, you can create ` Scope ` , fork background computations or run other flows asynchronously.
651
+ As part of the callback, you can create a ` Scope ` , fork background computations or run other flows asynchronously.
655
652
However, take care ** not** to share the ` FlowEmit ` instance across threads. That is, instances of ` FlowEmit ` are
656
- thread-unsafe and should only be used on the calling thread.
657
- The lifetime of ` FlowEmit ` should not extend over the duration of the invocation of ` usingEmit ` .
653
+ thread-unsafe and should only be used on the calling thread. The lifetime of ` FlowEmit ` should not extend over the
654
+ duration of the invocation of ` usingEmit ` .
658
655
659
656
Any asynchronous communication should be best done with ` Channel ` s. You can then manually forward any elements received
660
657
from a channel to ` emit ` , or use e.g. ` FlowEmit.channelToEmit ` .
@@ -727,18 +724,17 @@ Processes the elements one-by-one on the thread that is invoking the run method.
727
724
### Transforming flows: concurrency
728
725
729
726
A number of flow transformations introduces asynchronous boundaries. For example,
730
- ` .mapPar(int parallelism, Function<T,U> mappingFunction) ` describes a flow,
731
- which runs the pipeline defined so far in the background, emitting elements to a ` channel ` . Another ` fork ` reads these
732
- elements and runs up to ` parallelism ` invocations of ` mappingFunction ` concurrently. Mapped elements are then emitted by
733
- the returned flow.
727
+ ` .mapPar(int parallelism, Function<T,U> mappingFunction) ` describes a flow, which runs the pipeline defined so far in
728
+ the background, emitting elements to a ` channel ` . Another ` fork ` reads these elements and runs up to ` parallelism `
729
+ invocations of ` mappingFunction ` concurrently. Mapped elements are then emitted by the returned flow.
734
730
735
731
Behind the scenes, a new concurrency ` Scope ` is created along with a number of forks. In case of any exceptions,
736
732
everything is cleaned up before the flow propagates the exceptions. The ` .mapPar ` logic ensures that any exceptions from
737
733
the preceding pipeline are propagated through the channel.
738
734
739
735
Some other stages which introduce concurrency include ` .merge ` , ` .interleave ` , ` .groupedWithin ` and ` I/O ` stages. The
740
736
created channels serve as buffers between the pipeline stages, and their capacity is defined by the ` ScopedValue `
741
- ` Channel.BUFFER_SIZE ` in the scope, or default ` Channel.DEFAULT_BUFFER_SIZE ` is used.
737
+ ` Flow.CHANNEL_BUFFER_SIZE ` in the scope, or default ` Channel.DEFAULT_BUFFER_SIZE ` is used.
742
738
743
739
Explicit asynchronous boundaries can be inserted using ` .buffer() ` . This might be useful if producing the next element
744
740
to emit, and consuming the previous should run concurrently; or if the processing times of the consumer varies, and the
@@ -776,11 +772,10 @@ the pipeline described by the flow, and emits its elements onto the returned cha
776
772
### Text transformations and I/O operations
777
773
778
774
For smooth operations on ` byte[] ` , we've created a wrapper class ` ByteChunk ` . And for smooth type handling we created a
779
- dedicated ` ByteFlow ` , a subtype of ` Flow<ByteChunk> ` .
780
- To be able to utilize text and I/O operations, you need to create or transform into ` ByteFlow ` . It can be created via
781
- ` Flows.fromByteArray ` or ` Flows.fromByteChunk ` .
782
- ` Flow ` containing ` byte[] ` or ` ByteChunk ` can be transformed by using ` toByteFlow() ` method. Any other flow can be
783
- transformed by using ` toByteFlow() ` with mapping function.
775
+ dedicated ` ByteFlow ` , a subtype of ` Flow<ByteChunk> ` . To be able to utilize text and I/O operations, you need to create
776
+ or transform into ` ByteFlow ` . It can be created via ` Flows.fromByteArray ` or ` Flows.fromByteChunk ` . ` Flow ` containing
777
+ ` byte[] ` or ` ByteChunk ` can be transformed by using ` toByteFlow() ` method. Any other flow can be transformed by using
778
+ ` toByteFlow() ` with mapping function.
784
779
785
780
#### Text operations
786
781
@@ -858,4 +853,4 @@ We offer commercial development services. [Contact us](https://softwaremill.com)
858
853
859
854
## Copyright
860
855
861
- Copyright (C) 2023-2024 SoftwareMill [ https://softwaremill.com ] ( https://softwaremill.com ) .
856
+ Copyright (C) 2023-2025 SoftwareMill [ https://softwaremill.com ] ( https://softwaremill.com ) .
0 commit comments