An interviewer asked me that
How can you implement a class Foo, where you will be able to count
instances of that class. There are more threads which are creating
instance of that class Foo.
I replyed that with following code
public class Foo {
private static int count = 0;
public Foo() {
incrementCount();
}
public void incrementCount() {
synchronize (Foo.class) {
count++;
}
}
}
She again asked me that
If a thread ends, counter should be decrement, how can you do that?
I didn’t answer this question.
I know about finalize() method, but it depends on Garbage collector that when this method will be called, even if we override finalize().
I have no solution yet, can you explain it please?
You could wrap the Thread’s
Runnableinside anotherRunnablethat would decrement the counter:The problem with this is if the
Runnable rcreates multiple instances of Foo. You’d have to somehow track how many instances the thread created. You could do so using aThreadLocal<Integer>, and then calldecrementCounter(), in thefinallyblock, the appropriate number of times. See below for a complete, working example.If you can avoid it, you should not rely on the behavior of the GC as it is quite impredictable! If you insist into dealing with the Garbage Collector, then you should use reference queues — and to use it properly, you should study the concept of object reachability: http://docs.oracle.com/javase/7/docs/api/index.html?java/lang/ref/package-summary.html
As a final note, if I were interviewing you, I’d try to make you realize that the code you propose does not perfectly satisfy the requirements: you’d have to make the class
final, or the methodincrementCount()finalorprivate. Or, easier, you could increment the count in an instance initializer block: no need to think about methods being overriden in subclasses or newly added constructors not incrementing the count.A complete example:
This way, you can feed this ThreadFactory to a thread pool, for example, or you can use it yourself when you want to build a thread:
(new FooCountingThreadFactory()).newThread(job);Anyways, there’s still a problem with this approach: if a thread creates instances of
Fooand stores them on global scope (read:staticfields), then these instances will still be alive after the thread has died, and the counter will all the same be decremented to 0.