Skip to main content
Updated description to match code
Source Link
Gili
  • 90.9k
  • 109
  • 417
  • 732
  • ForkJoinPool was executing tasks using different worker threads (with different names) if the worker thread became idle long enough. For example, if the main thread got suspended on a debugging breakpoint, the worker thread would become idle and shut down. When I would resume execution, ForkJoinThread would spin up a new worker thread with a different name. To solve this, I had to provide a custom ForkJoinWorkerThreadFactory implementation that returns null if the ForkJoinPool already has a live workerprovide a custom (this prevents the pool from creating multiple workers)ForkJoinWorkerThreadFactory implementation that ensures only one thread runs at a time, and that its name is hard-coded. I also had ensure that my code was returning the same Random instance even if a worker thread shut down and came back again.
  • Collections with non-deterministic iteration order such as HashMap or HashSet led to elements grabbing random numbers in a different order on every run. I corrected this by using LinkedHashMap and LinkedHashSet.
  • Objects with non-deterministic hashCode() implementations, such as Enum.hashCode(). I forget what problems this caused but I corrected it by calculating the hashCode() myself instead of relying on the built-in method.
  • ForkJoinPool was executing tasks using different worker threads (with different names) if the worker thread became idle long enough. For example, if the main thread got suspended on a debugging breakpoint, the worker thread would become idle and shut down. When I would resume execution, ForkJoinThread would spin up a new worker thread with a different name. To solve this, I had to provide a custom ForkJoinWorkerThreadFactory implementation that returns null if the ForkJoinPool already has a live worker (this prevents the pool from creating multiple workers). I also had ensure that my code was returning the same Random instance even if a worker thread shut down and came back again.
  • Collections with non-deterministic iteration order such as HashMap or HashSet led to elements grabbing random numbers in a different order on every run. I corrected this by using LinkedHashMap and LinkedHashSet.
  • Objects with non-deterministic hashCode() implementations, such as Enum.hashCode(). I forget what problems this caused but I corrected it by calculating the hashCode() myself instead of relying on the built-in method.
  • ForkJoinPool was executing tasks using different worker threads (with different names) if the worker thread became idle long enough. For example, if the main thread got suspended on a debugging breakpoint, the worker thread would become idle and shut down. When I would resume execution, ForkJoinThread would spin up a new worker thread with a different name. To solve this, I had to provide a custom ForkJoinWorkerThreadFactory implementation that ensures only one thread runs at a time, and that its name is hard-coded. I also had ensure that my code was returning the same Random instance even if a worker thread shut down and came back again.
  • Collections with non-deterministic iteration order such as HashMap or HashSet led to elements grabbing random numbers in a different order on every run. I corrected this by using LinkedHashMap and LinkedHashSet.
  • Objects with non-deterministic hashCode() implementations, such as Enum.hashCode(). I forget what problems this caused but I corrected it by calculating the hashCode() myself instead of relying on the built-in method.
Fixed broken link
Source Link
Gili
  • 90.9k
  • 109
  • 417
  • 732
  • ForkJoinPool was executing tasks using different worker threads (with different names) if the worker thread became idle long enough. For example, if the main thread got suspended on a debugging breakpoint, the worker thread would become idle and shut down. When I would resume execution, ForkJoinThread would spin up a new worker thread with a different name. To solve this, I had to provide a custom ForkJoinWorkerThreadFactory implementation that returns null if the ForkJoinPool already has a live workerprovide a custom ForkJoinWorkerThreadFactory implementation that returns null if the ForkJoinPool already has a live worker (this prevents the pool from creating multiple workers). I also had ensure that my code was returning the same Random instance even if a worker thread shut down and came back again.
  • Collections with non-deterministic iteration order such as HashMap or HashSet led to elements grabbing random numbers in a different order on every run. I corrected this by using LinkedHashMap and LinkedHashSet.
  • Objects with non-deterministic hashCode() implementations, such as Enum.hashCode(). I forget what problems this caused but I corrected it by calculating the hashCode() myself instead of relying on the built-in method.
  • ForkJoinPool was executing tasks using different worker threads (with different names) if the worker thread became idle long enough. For example, if the main thread got suspended on a debugging breakpoint, the worker thread would become idle and shut down. When I would resume execution, ForkJoinThread would spin up a new worker thread with a different name. To solve this, I had to provide a custom ForkJoinWorkerThreadFactory implementation that returns null if the ForkJoinPool already has a live worker (this prevents the pool from creating multiple workers). I also had ensure that my code was returning the same Random instance even if a worker thread shut down and came back again.
  • Collections with non-deterministic iteration order such as HashMap or HashSet led to elements grabbing random numbers in a different order on every run. I corrected this by using LinkedHashMap and LinkedHashSet.
  • Objects with non-deterministic hashCode() implementations, such as Enum.hashCode(). I forget what problems this caused but I corrected it by calculating the hashCode() myself instead of relying on the built-in method.
  • ForkJoinPool was executing tasks using different worker threads (with different names) if the worker thread became idle long enough. For example, if the main thread got suspended on a debugging breakpoint, the worker thread would become idle and shut down. When I would resume execution, ForkJoinThread would spin up a new worker thread with a different name. To solve this, I had to provide a custom ForkJoinWorkerThreadFactory implementation that returns null if the ForkJoinPool already has a live worker (this prevents the pool from creating multiple workers). I also had ensure that my code was returning the same Random instance even if a worker thread shut down and came back again.
  • Collections with non-deterministic iteration order such as HashMap or HashSet led to elements grabbing random numbers in a different order on every run. I corrected this by using LinkedHashMap and LinkedHashSet.
  • Objects with non-deterministic hashCode() implementations, such as Enum.hashCode(). I forget what problems this caused but I corrected it by calculating the hashCode() myself instead of relying on the built-in method.
Catch InterruptedException
Source Link
Gili
  • 90.9k
  • 109
  • 417
  • 732
class MyForkJoinWorkerThread extends ForkJoinWorkerThread { MyForkJoinWorkerThread(ForkJoinPool pool) { super(pool); // Change thread name after ForkJoinPool.registerWorker() does the same setName("DETERMINISTIC_WORKER"); } } ForkJoinWorkerThreadFactory factory = new ForkJoinWorkerThreadFactory() { private WeakReference<Thread> currentWorker = new WeakReference<>(null); @Override public synchronized ForkJoinWorkerThread newThread(ForkJoinPool pool) { // If the pool already has a live thread, wait for it to shut down. Thread thread = currentWorker.get(); if (thread != null && thread.isAlive()) { try {  thread.join(); } catch (InterruptedException e) { log.error("", e); } } ForkJoinWorkerThread result = new MyForkJoinWorkerThread(pool); currentWorker = new WeakReference<>(result); return result; } }; 
class MyForkJoinWorkerThread extends ForkJoinWorkerThread { MyForkJoinWorkerThread(ForkJoinPool pool) { super(pool); // Change thread name after ForkJoinPool.registerWorker() does the same setName("DETERMINISTIC_WORKER"); } } ForkJoinWorkerThreadFactory factory = new ForkJoinWorkerThreadFactory() { private WeakReference<Thread> currentWorker = new WeakReference<>(null); @Override public synchronized ForkJoinWorkerThread newThread(ForkJoinPool pool) { // If the pool already has a live thread, wait for it to shut down. Thread thread = currentWorker.get(); if (thread != null && thread.isAlive()) thread.join(); ForkJoinWorkerThread result = new MyForkJoinWorkerThread(pool); currentWorker = new WeakReference<>(result); return result; } }; 
class MyForkJoinWorkerThread extends ForkJoinWorkerThread { MyForkJoinWorkerThread(ForkJoinPool pool) { super(pool); // Change thread name after ForkJoinPool.registerWorker() does the same setName("DETERMINISTIC_WORKER"); } } ForkJoinWorkerThreadFactory factory = new ForkJoinWorkerThreadFactory() { private WeakReference<Thread> currentWorker = new WeakReference<>(null); @Override public synchronized ForkJoinWorkerThread newThread(ForkJoinPool pool) { // If the pool already has a live thread, wait for it to shut down. Thread thread = currentWorker.get(); if (thread != null && thread.isAlive()) { try {  thread.join(); } catch (InterruptedException e) { log.error("", e); } } ForkJoinWorkerThread result = new MyForkJoinWorkerThread(pool); currentWorker = new WeakReference<>(result); return result; } }; 
Fix race-condition by join()ing on the existing thread
Source Link
Gili
  • 90.9k
  • 109
  • 417
  • 732
Loading
Added sample implementation of ForkJoinWorkerThreadFactory
Source Link
Gili
  • 90.9k
  • 109
  • 417
  • 732
Loading
Explained how to prevent ForkJoinPool for spinning up multiple workers
Source Link
Gili
  • 90.9k
  • 109
  • 417
  • 732
Loading
Must return the same Random instance even if threads die and come back again
Source Link
Gili
  • 90.9k
  • 109
  • 417
  • 732
Loading
Figured out why worker thread names were changing
Source Link
Gili
  • 90.9k
  • 109
  • 417
  • 732
Loading
Figured out why worker thread names were changing
Source Link
Gili
  • 90.9k
  • 109
  • 417
  • 732
Loading
deleted 4 characters in body
Source Link
Gili
  • 90.9k
  • 109
  • 417
  • 732
Loading
added 198 characters in body
Source Link
Gili
  • 90.9k
  • 109
  • 417
  • 732
Loading
Answer turns out to be wrong
Source Link
Gili
  • 90.9k
  • 109
  • 417
  • 732
Loading
Source Link
Gili
  • 90.9k
  • 109
  • 417
  • 732
Loading