I am trying to make an Object Pool, program and output is given below.
The issue I am facing here is that after leaving the object and calling notify or notifyAll (line 1 highlighted in program), the waiting threads does not get started.
Can anyone please help in resolving this issue please?
Program :-
import java.util.Hashtable;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
class ObjectPool implements Callable
{
//Integer o;
public ObjectPool()
{
//o = i;
}
public static ConcurrentLinkedQueue<Integer> locked = new ConcurrentLinkedQueue<Integer>();
public static ConcurrentLinkedQueue<Integer> unlocked = new ConcurrentLinkedQueue<Integer>();
static
{
int one = 1;
int two = 2;
int three = 3;
int four = 4;
unlocked.add(one);
unlocked.add(two);
unlocked.add(three);
unlocked.add(four);
}
public Object get() throws InterruptedException
{
if(unlocked.size()>0)
{
Integer i = (Integer) unlocked.poll();
//Integer o = new Integer((Integer) locked.size());
locked.add(i);
//System.out.println("New Object Created : "+o.toString()+" and acquired by Thread : "+Thread.currentThread().getName()+" for Object this : "+this.toString());
return (i);
}
else
{
synchronized(this)
{
System.out.println("Thread entering into waiting state : "+Thread.currentThread().getName()+" for Object this : "+this.toString());
wait();
get();
return null;
}
}
}
public void leave()
{
synchronized(this)
{
// System.out.println(" Object left : "+o.toString()+" by Thread : "+Thread.currentThread().getName()+" for Object this : "+this.toString());
Integer left = (Integer) locked.poll();
unlocked.add(left);
notify(); **// Line 1**
}
}
@Override
public Object call() throws Exception
{
Object o1 = get();
System.out.println( "Thread going to sleep after getting lock : "+Thread.currentThread().getName()+".."+o1.toString());
Thread.sleep(5000);
System.out.println( "Thread Giving Notification : "+Thread.currentThread().getName()+".."+o1.toString());
leave();
return o1;
}
}
public class Driver
{
public static void main(String[] args) throws InterruptedException, ExecutionException
{
System.out.println(" Main method");
ObjectPool[] op = {new ObjectPool(),new ObjectPool(),new ObjectPool(),new ObjectPool(),new ObjectPool(),new ObjectPool(),new ObjectPool(),new ObjectPool()};
ExecutorService es = Executors.newFixedThreadPool(8);
for(ObjectPool o :op)
{
es.submit(o);
}
//System.out.println(" p1 to p4 will leave the lock now");
}
}
Output :-
Main method
Thread going to sleep after getting lock : pool-1-thread-1..1
Thread going to sleep after getting lock : pool-1-thread-3..2
Thread going to sleep after getting lock : pool-1-thread-2..3
Thread going to sleep after getting lock : pool-1-thread-5..4
Thread entering into waiting state : pool-1-thread-8 for Object this : ObjectPool@7bedda88
Thread entering into waiting state : pool-1-thread-6 for Object this : ObjectPool@43cdad4b
Thread entering into waiting state : pool-1-thread-7 for Object this : ObjectPool@5e990133
Thread Giving Notification : pool-1-thread-3..2
Thread Giving Notification : pool-1-thread-5..4
Thread Giving Notification : pool-1-thread-1..1
Thread Giving Notification : pool-1-thread-2..3
When you want to synchronize multiple threads, you should synchronize them on the same object, not on this.
The wait
method should be used in while loop, for example:
while (unlocked.size() == 0) {
System.out.println("Thread entering into waiting state : "+Thread.currentThread().getName()+" for Object this : "+this.toString());
this.getClass().wait();
}
This code works fine on my machine, try it
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
class ObjectPool implements Callable {
public static ConcurrentLinkedQueue<Integer> locked = new ConcurrentLinkedQueue<>();
public static ConcurrentLinkedQueue<Integer> unlocked = new ConcurrentLinkedQueue<>();
static {
int one = 1;
int two = 2;
int three = 3;
int four = 4;
unlocked.add(one);
unlocked.add(two);
unlocked.add(three);
unlocked.add(four);
}
public Object get() throws InterruptedException {
synchronized (getClass()) {
while (unlocked.size() == 0) {
System.out.println("Thread entering into waiting state : "+Thread.currentThread().getName()+" for Object this : "+this.toString());
this.getClass().wait();
}
Integer i = unlocked.poll();
locked.add(i);
return i;
}
}
public void leave() {
synchronized (getClass()) {
Integer left = locked.poll();
unlocked.add(left);
this.getClass().notifyAll();
}
}
@Override
public Object call() throws Exception {
Object o1 = get();
System.out.println("Thread going to sleep after getting lock : " + Thread.currentThread().getName() + ".." + o1.toString());
Thread.sleep(5000);
System.out.println("Thread Giving Notification : " + Thread.currentThread().getName() + ".." + o1.toString());
leave();
return o1;
}
}
public class Driver {
public static void main(String[] args) throws InterruptedException, ExecutionException {
System.out.println(" Main method");
ObjectPool[] op = {new ObjectPool(), new ObjectPool(), new ObjectPool(), new ObjectPool(), new ObjectPool(), new ObjectPool(), new ObjectPool(), new ObjectPool()};
ExecutorService es = Executors.newFixedThreadPool(8);
for (ObjectPool o : op) {
es.submit(o);
}
}
}
Output:
Main method
Thread going to sleep after getting lock : pool-1-thread-3..4
Thread going to sleep after getting lock : pool-1-thread-1..1
Thread going to sleep after getting lock : pool-1-thread-5..2
Thread entering into waiting state : pool-1-thread-8 for Object this : hello.ObjectPool@62b3e25e
Thread entering into waiting state : pool-1-thread-6 for Object this : hello.ObjectPool@5b14447a
Thread entering into waiting state : pool-1-thread-2 for Object this : hello.ObjectPool@766f2b2c
Thread entering into waiting state : pool-1-thread-7 for Object this : hello.ObjectPool@3d804bcd
Thread going to sleep after getting lock : pool-1-thread-4..3
Thread Giving Notification : pool-1-thread-3..4
Thread going to sleep after getting lock : pool-1-thread-8..1
Thread entering into waiting state : pool-1-thread-7 for Object this : hello.ObjectPool@3d804bcd
Thread Giving Notification : pool-1-thread-1..1
Thread Giving Notification : pool-1-thread-5..2
Thread entering into waiting state : pool-1-thread-2 for Object this : hello.ObjectPool@766f2b2c
Thread entering into waiting state : pool-1-thread-6 for Object this : hello.ObjectPool@5b14447a
Thread going to sleep after getting lock : pool-1-thread-6..2
Thread entering into waiting state : pool-1-thread-7 for Object this : hello.ObjectPool@3d804bcd
Thread going to sleep after getting lock : pool-1-thread-2..3
Thread Giving Notification : pool-1-thread-4..3
Thread going to sleep after getting lock : pool-1-thread-7..4
Thread Giving Notification : pool-1-thread-8..1
Thread Giving Notification : pool-1-thread-2..3
Thread Giving Notification : pool-1-thread-6..2
Thread Giving Notification : pool-1-thread-7..4