javamultithreadingwaitnotifyobject-pooling

Object Pool notify not working


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

Solution

  • 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