{"id":18024071,"url":"https://github.com/thomasnield/tom-sync","last_synced_at":"2025-04-04T18:27:40.258Z","repository":{"id":29405675,"uuid":"32941087","full_name":"thomasnield/tom-sync","owner":"thomasnield","description":"A Java 8 library with helpful concurrency tools, inlcuding lazy initializers and synchronizers","archived":false,"fork":false,"pushed_at":"2016-05-26T15:20:17.000Z","size":24,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-02-10T03:43:02.349Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/thomasnield.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-03-26T17:08:52.000Z","updated_at":"2018-10-14T22:37:37.000Z","dependencies_parsed_at":"2022-09-04T18:11:00.241Z","dependency_job_id":null,"html_url":"https://github.com/thomasnield/tom-sync","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thomasnield%2Ftom-sync","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thomasnield%2Ftom-sync/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thomasnield%2Ftom-sync/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thomasnield%2Ftom-sync/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/thomasnield","download_url":"https://codeload.github.com/thomasnield/tom-sync/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247228241,"owners_count":20904833,"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","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":[],"created_at":"2024-10-30T07:11:49.712Z","updated_at":"2025-04-04T18:27:40.234Z","avatar_url":"https://github.com/thomasnield.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"Welcome to the tom-sync Java library. These are my concurrency tools and I hope you find value in them too.\n\nYou will need Java 8 to use this library as it requires the functional interfaces and Optionals. \n\nSo far there are only two core features: Lazy Initialization wrappers and the `BufferedLatch`. \n\n**BufferedLatch**\n\nThe `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. \n\nA 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.\n\nThink of it as a fork-join on an unknown number of asynchronous tasks.\n\n```\nResultSet rs = ...;\nExecutorService service = ...;\nBufferedLatch bufferedLatch = new BufferedLatch();\n\n//iterate a ResultSet, extract a String from each one, and pass it off to the executor as a task to process\nwhile (rs.next()) { \n    bufferedLatch.incrementLeadCount();\n    final String reportCode = rs.getString(\"REPORT_CODE\");\n    \n    service.execute(() -\u003e {\n        processReport(reportCode);\n        bufferedLatch.incrementChaseCount();\n    });\n}\nbufferedLatch.setLeaderComplete();\nbufferedLatch.await();\n```\n\n**Lazy Initialization**\n\nThe Lazy Initialization wrappers streamline the task of deferring and caching the calculation of a value, and doing so in a threadsafe manner.\n\n`LazyObject\u003cBigDecimal\u003e balance = LazyObject.forSupplier(() -\u003e calculateBalance(financeDate));`\n\nWhen `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. \n\n`public BigDecimal getBalance() { \n    return balance.get();\n}`\n\nThere 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.\n\n`LazyInt`\n\n`LazyLong`\n\n`LazyFloat`\n\n`LazyBoolean`\n\n`LazyDouble`\n\n\n\n**Lazy Expirable**\n\nThere 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\u003cT\u003e`, 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. \n\nThe static factory signature is\n\n`public static \u003cT\u003e LazyExpirable\u003cT\u003e forSupplier(Supplier\u003cT\u003e supplier, ScheduledThreadPoolExecutor executor, long expirationDelay, TimeUnit timeUnit)`\n\nTherefore, to create a `MarketEngine` type that caches but expires after 5 minutes of no use, call this code. \n\n`LazyExpirable\u003cMarketEngine\u003e marketEngine = LazyExpirable.forSupplier(() -\u003e MarketEngine.create(), scheduledExecutor, 5L, TimeUnit.MINUTES);`\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthomasnield%2Ftom-sync","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthomasnield%2Ftom-sync","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthomasnield%2Ftom-sync/lists"}