I recently had a problem with two threads sticking in deadlock because they weren’t monitoring the same object the way I thought they were. As it turned out, implementing the Singleton pattern solved the problem. But why?
I only instantiated one instance of the class of which the object was a private property, so I expected it to be effectively singleton anyway.
For the sake of completeness of the question, here is also some code illustrating the difference:
Before the Singleton pattern was implemented:
class Worker {
private BlockingQueue q = new LinkedBlockingQueue();
public void consume(String s) {
// Called by thread 1.
// Waits until there is anything in the queue, then consumes it
}
public void produce(String s) {
// Called by thread 2.
// Puts an object in the queue.
}
// Actually implements Runnable, so there's a run() method here too...
}
The threads were started like this:
Worker w = new Worker();
new Thread(w).start();
// Producer also implements Runnable. It calls produce on its worker.
Producer p = new Producer(w);
new Thread(p).start();
Now, when I examined the queues that were actually used in produce() and consume(), System.identityHashCode(q) gave different results in the different threads.
With the singleton pattern:
class Worker {
private static BlockingQueue q;
private BlockingQueue getQueue() {
if(q == null) {
q = new LinkedBlockingQueue();
}
return q;
}
// The rest is unchanged...
}
Suddenly, it works. Why is this pattern necessary here?
The problem is that you are creating a
new Worker()inside theServerconstructor. You have this: