https://github.com/thomasnield/tom-sync
A Java 8 library with helpful concurrency tools, inlcuding lazy initializers and synchronizers
https://github.com/thomasnield/tom-sync
Last synced: about 1 year ago
JSON representation
A Java 8 library with helpful concurrency tools, inlcuding lazy initializers and synchronizers
- Host: GitHub
- URL: https://github.com/thomasnield/tom-sync
- Owner: thomasnield
- Created: 2015-03-26T17:08:52.000Z (about 11 years ago)
- Default Branch: master
- Last Pushed: 2016-05-26T15:20:17.000Z (about 10 years ago)
- Last Synced: 2025-02-10T03:43:02.349Z (over 1 year ago)
- Language: Java
- Homepage:
- Size: 23.4 KB
- Stars: 2
- Watchers: 3
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
Welcome to the tom-sync Java library. These are my concurrency tools and I hope you find value in them too.
You will need Java 8 to use this library as it requires the functional interfaces and Optionals.
So far there are only two core features: Lazy Initialization wrappers and the `BufferedLatch`.
**BufferedLatch**
The `BufferedLatch` is a synchronizer much like a `CountDownLatch`, but it is used for situations where the "count" is not known until later. It positively increments two `int` counts, the `leadCount` and the `chaseCount`. The `leadCount` is the leader and incremented by calling `incrementLeadCount()`, and the `chaseCount` chases it by calling `incrementChaseCount()`. When both counts are equal and `setLeaderComplete()` is called, anything waiting on the `BufferedLatch` is notified.
A typical use of `BufferedLatch` is to iterate a `ResultSet` or some buffered data set, process each one asynchronously (be careful to extract the data first to prevent race conditions!), and then wait for all tasks to finish.
Think of it as a fork-join on an unknown number of asynchronous tasks.
```
ResultSet rs = ...;
ExecutorService service = ...;
BufferedLatch bufferedLatch = new BufferedLatch();
//iterate a ResultSet, extract a String from each one, and pass it off to the executor as a task to process
while (rs.next()) {
bufferedLatch.incrementLeadCount();
final String reportCode = rs.getString("REPORT_CODE");
service.execute(() -> {
processReport(reportCode);
bufferedLatch.incrementChaseCount();
});
}
bufferedLatch.setLeaderComplete();
bufferedLatch.await();
```
**Lazy Initialization**
The Lazy Initialization wrappers streamline the task of deferring and caching the calculation of a value, and doing so in a threadsafe manner.
`LazyObject balance = LazyObject.forSupplier(() -> calculateBalance(financeDate));`
When `balance` has the `get()` method first called, it will calculate and cache the value given the provided `Supplier`. After the value is cached, it avoids unnecessary synchronization to improve concurrency.
`public BigDecimal getBalance() {
return balance.get();
}`
There are different primitive flavors of `LazyObject` as well. These will store a lazy primitive instead of an object much like the `Optional` has `OptionalInt`, `OptionalLong`, and `OptionalDouble` counterparts.
`LazyInt`
`LazyLong`
`LazyFloat`
`LazyBoolean`
`LazyDouble`
**Lazy Expirable**
There is also a `LazyExpirable` which behaves identically to a `LazyObject`, but the cached value will expire after a specified time period of no use. It uses a `Supplier`, a `ScheduledThreadPoolExecutor` and time interval specified by the client. When `get()` is first called, the object will be created and cached. But if `get()` is not called again for the specified time period, it will expire and clear the cache, causing the next call to `get()` to rebuild the object. However, if `get()` is called before the value expires, the countdown to expiration will restart.
The static factory signature is
`public static LazyExpirable forSupplier(Supplier supplier, ScheduledThreadPoolExecutor executor, long expirationDelay, TimeUnit timeUnit)`
Therefore, to create a `MarketEngine` type that caches but expires after 5 minutes of no use, call this code.
`LazyExpirable marketEngine = LazyExpirable.forSupplier(() -> MarketEngine.create(), scheduledExecutor, 5L, TimeUnit.MINUTES);`