4

I'm using a custom class Foo in Java as the key type in a HashMap. All the fields of Foo instances are immutable (they are declared final and private and are assigned values only in the constructor). Thus, the hashCode() of a given Foo object is also fixed, and for optimization purposes, I am calculating it in the constructor and simply returning that value in the hashCode() method.

Instances of Foo also have a value() method which returns a similar fixed value once the object has been instantiated. Currently I am also calculating it in the constructor and returning it in the method, but there is a difference between hashCode() and value(): hashCode() is called for the first time almost instantly after the object is created, but value() is called much later. I understand that having a separate Thread to calculate the hash-code would simply increase the run-time because of synchronization issues, but:

  • is this a good way to calculate value()? Would it improve run-time at all?
  • are simple Threads enough, or do I need to use pools etc.?

Note: this may seem like I'm optimizing the wrong parts of my program, but I've already worked on the 'correct' parts and brought the average run-time down from ~17 seconds to ~2 seconds. Edit: there will be upwards of 5000 Foo objects, and that's a conservative estimate.

2
  • in terms of conception and architecture, it would be weird, as value() would be able to return an invalid value for a time. Commented Apr 16, 2016 at 16:56
  • @njzk2 That's fine for my program; as I said, value() is called a long time after the object is created. Commented Apr 16, 2016 at 16:59

2 Answers 2

2

It definitely sounds like deferred calculation is a good approach here - and yes, if you create a lot of these objects, a thread pool is the way to go.

As for value()'s return value until it's ready, I would stay away from returning invalid values, and instead either make it blocking (and add some isValueReady() helper) or make it instantly return a "future" - some object that offers those same isReady and a blocking get methods.

Also, never rely on "much later" - always make sure the value there is ready before using it.

Sign up to request clarification or add additional context in comments.

2 Comments

In theory, your answer sounds right to me, but in practice, something's going wrong: the program is taking more than 5 times the usual time to run. Which details should I provide to make my situation more specific?
@shardulc There are many possible variables, and I don't know your application. I would first look at two things: 1. how heavy is calculating value()? If creating a threadpool thread is heavier, it will never be worth it. 2. How CPU-starved is your application? If it has 100% CPU utilization, deferring a calculation will carry no benefit and you will still pay for the overhead. Honestly though, it might be something else altogether... I rely on profiling when it isn't obvious from the code or from debugging why something is slow.
1

I recommend creating a Future for value - create a static fixedTheadPool and submit the value calculations on it. This way there's no risk that value will be accessed before it's available - the worst case is that whatever is accessing value will block on a Future.get call (or use the version with a timeout if e.g. deadlock is a concern)

Because Future.get throws checked exceptions which can be a nuisance, you can wrap the get call in your class's getter method and wrap the checked exceptions in a RuntimeException

class MyClass { private static final ExecutorService executor = Executors.newFixedThreadPool(/* some value that makes sense */); private final Future<Value> future; public MyClass() { future = executor.submit(/* Callable */); } public boolean isValueDone() { return future.isDone(); } public Value value() { try { return future.get(); } catch(InterruptedException|ExecutionException e) { throw new RuntimeException(e); } } } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.