-3

Need help with code at below link as it should run indefinitely likewise with any typical producer/consumer problem but somehow it is getting stuck on call of condition.signal(). What am I doing wrong here?

In main method, I have created two thread, one is consumer and other one is producer. it has shared task queue where both updates the entry.

package com.anurgup.handson;

import java.util.PriorityQueue;
import java.util.Queue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class ConditionService implements Runnable {

    Lock lock = new ReentrantLock();
    Condition added = lock.newCondition();
    Condition removed = lock.newCondition();

    // type of service
    String type;

    // shared task for insertion and deletion of task
    static Queue<Integer> task = new PriorityQueue<Integer>();

    // max number of task allowed
    private static final int MAX_SIZE = 5;

    public ConditionService(String type) {
        this.type = type;
    }

    public static void main(String[] args) {

        ExecutorService service = Executors.newFixedThreadPool(2);
        service.submit(new ConditionService("producer"));
        service.submit(new ConditionService("consumer"));

    }

    public void produce() {
        try {
            while (true) {
                System.out.println("in producer...");
                synchronized (task) {
                    while (task.size() == MAX_SIZE)
                        removed.await();
                    System.out.println("added item: " + task.size());
                    task.add(task.size());
                    added.signal();
                }
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public void consume() {
        try {
            while (true) {
                System.out.println("in consumer...");
                synchronized (task) {
                    while (task.isEmpty())
                        added.await();
                    System.out.println("removed item: " + task.peek());
                    task.remove();
                    removed.signal();
                }
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        if (this.type.equals("producer"))
            this.produce();
        else
            this.consume();
    }
}
Anuraag
  • 33
  • 4

1 Answers1

1

You're making two mistakes. First, your lock and conditions need to be static, or each task will only synchronize and wait on itself. Second, you need to use lock.lock(), not synchronized. It should look like this:

lock.lock();
try {
    // wait
    // produce/consume
} finally {
    lock.unlock();
}
shmosel
  • 49,289
  • 6
  • 73
  • 138
  • thanks!..it worked. Although I understood why I need to use static for locks and condition here but I don't get the difference with using synchronised block and lock.lock(). could you please explain. – Anuraag Jun 29 '19 at 04:33
  • They're entirely separate types of locks. Look up implicit vs. explicit locks. – shmosel Jun 30 '19 at 04:34