0

I have written this code, an implement of blocking queue:

public class MyBlockingQueue extends Thread{

 final private List <Integer> queue;

  public MyBlockingQueue(){
      queue = new LinkedList<Integer>();
  }

  public synchronized int size () {

            return queue.size();

  }

  public synchronized void enqueue(int num)
  throws InterruptedException  {

    this.queue.add(num);
    System.out.println(getName()+" "+num+" added");
    notify();
  }

  public synchronized int dequeue()
  throws InterruptedException{
      while(queue.size() == 0)
          wait();

    return this.queue.remove(0);
  }

1.I have tried to make two threads and force them to add some number to the queue and then remove it. Unfortunatley, it seems like each thread has its own object. how can I change the code so both threads will handle the same object and add/remove to the same blocking queue synchronously?

2.Have I write the dequeue function correctly (so that when one thread removes the last number from the queue and the queue size is now zero, other threads will wait until the enqueue will notify them ) ?

this is my tester:

public class Main  {
    //checks the blocking queue
public static void main(String[] args) throws InterruptedException {
    final MyBlockingQueue mine = new MyBlockingQueue();
    Thread t1 = new Thread(){
        public void run(){
            try {


                mine.enqueue((int)(Math.random()*1000));
                System.out.println(getName()+"<- enter");

                } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            };
        }
    };

    Thread t2 = new Thread(){
        public void run(){
            try {


                mine.dequeue();
                System.out.println(getName()+"<-remove");

            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    };

    Thread t3 = new Thread(){
        public void run(){
            try {


                mine.dequeue();
                System.out.println(getName()+"<-remove");

            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    };
    Thread t4 = new Thread(){
        public void run(){
            try {

                mine.enqueue((int)(Math.random()*1000));
                System.out.println(getName()+"<-enter");


                } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    };
    Thread t5 = new Thread(){
        public void run(){
            try {

                mine.dequeue();
                System.out.println(getName()+"<-remove");


                } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    };


    Thread t6 = new Thread(){
        public void run(){
            System.out.println("thread 6 of entering began, should release last thread of remove");
            try {

                mine.enqueue((int)(Math.random()*1000));
                System.out.println(getName()+"<-enter");


                } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    };
    Thread t7 = new Thread(){
        public void run(){
            try {

                mine.dequeue();
                System.out.println(getName()+"<-remove");


                } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    };
    Thread t8 = new Thread(){
        public void run(){
            try {

                mine.dequeue();
                System.out.println(getName()+"<-remove");


                } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    };
    Thread t9 = new Thread(){
        public void run(){
            try {

                mine.dequeue();
                System.out.println(getName()+"<-remove");


                } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    };
    Thread t10 = new Thread(){
        public void run(){
            try {

                mine.dequeue();
                System.out.println(getName()+"<-remove");


                } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    };
    Thread t11 = new Thread(){
        public void run(){
            System.out.println("thread 11 come to help, this comment before entering, after that we should see one add one remove");
            try {

                mine.enqueue((int)(Math.random()*1000));
                System.out.println(getName()+"<-enter");


                } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    };

    t1.start();
    t2.start();
    t3.start();
    Thread.sleep(5000);

    t4.start();//will the remove wai for the enter
    Thread.sleep(5000);
    /////4 tries to remove, one enter
    t5.start(); //requesting to remove before have something
    t7.start();
    t8.start();
    t9.start();
    t10.start();
    Thread.sleep(5000);
    t6.start();
    Thread.sleep(20000);//after 20 sec, t11 come to help
    t11.start();

}

}

here is the output:

   Thread-0 enqueued 1
Thread-1<- enter
Thread-0 dequeued 1
Thread-2<-remove
Thread-0 enqueued 4
Thread-0 dequeued 4
Thread-3<-remove
Thread-4<-enter
thread 6 of entering began, should release last thread of remove
Thread-0 enqueued 6
Thread-0 dequeued 6
Thread-5<-remove
Thread-6<-enter
thread 11 come to help, this comment before entering, after that we should see one add one remove
Thread-0 enqueued 11
Thread-0 dequeued 11
Thread-8<-remove
Thread-11<-enter
adi
  • 11
  • 2
  • 1
    Why `extends Thread`? A queue is not a kind of thread. – Solomon Slow Apr 25 '16 at 19:05
  • Re, "It seems like each thread has its own object. how can I change the code so both threads will handle the same object?" You have not shown us any code that uses your `MyBlockingQueue` class, so it's hard to say what might or might not be wrong with that code. – Solomon Slow Apr 25 '16 at 19:07
  • sorry, I attached a test code – adi Apr 25 '16 at 19:17
  • Please, show us the print results. For what I can see, your code is correct. (You should remove extends Thread, and the dequeue function has a problem, but all of that would still work on your test case) – Plínio Pantaleão Apr 25 '16 at 20:57
  • I have attached it – adi Apr 25 '16 at 21:42

2 Answers2

0

You need to make the queue static or pass the object to the threads upon initialization. If you don't do that the two threads will enque/dequeue on separate queues.

Limmen
  • 1,407
  • 11
  • 17
  • what should I turn to static- the list or the blocking queue? – adi Apr 25 '16 at 17:40
  • @Limmen has written exactly what should be static queue inside your MyBlockingQueue class – mariusz2108 Apr 25 '16 at 18:21
  • oh sorry, queue is my list. I have not noticed that. thank you! – adi Apr 25 '16 at 19:09
  • @adi, An object (e.g., a `List` or a `MyBlockingQueue`) can not be `static`. Only a _variable_ can be static. @Limmen is telling you to store a reference to a `MyBlockingQueue` object in a static variable, and then write code for your threads that uses that variable. – Solomon Slow Apr 25 '16 at 19:10
-1

For example:

public class MyBlockingQueue extends Thread {

    final private static List<Integer> queue = new LinkedList<Integer>();

    public synchronized int size() {

        return MyBlockingQueue.queue.size();

    }

    public synchronized void enqueue(int num) throws InterruptedException {

        MyBlockingQueue.queue.add(num);
        System.out.println(getName() + " enqueued " + num);
        notify();
    }

    public synchronized int dequeue() throws InterruptedException {
        while (MyBlockingQueue.queue.size() == 0) {
            wait();
        }
        System.out.println(getName() + " dequeued " + MyBlockingQueue.queue.get(0));
        return MyBlockingQueue.queue.remove(0);
    }
}
  • I think that I have suceed managing it In other way, but thank you!! By the way, is your code managing the problem that "when one thread removes the last number from the queue and the queue size is now zero, other threads will wait until the enqueue will notify them"? – adi Apr 25 '16 at 19:14
  • Its not mine, it is just your code with recommended above modifications. Good and right examples you can find in the source of the next files: ArrayBlockingQueue DelayQueue LinkedBlockingQueue PriorityBlockingQueue SynchronousQueue. Within java.util.concurrent package – Anton Vetrov Apr 25 '16 at 19:23
  • Should the size() function be syncronized? if it does, how can I make it syncroonized without writing the syncronized keyword? – adi Apr 25 '16 at 23:47
  • Pay attention as james large wrote "A queue is not a kind of thread". You can do not synchronize size() and use AtomicInteger count variable instead for persisting a size. Also instead of synchronized you can use ReentrantLock, here you can get an explanation [link](http://stackoverflow.com/questions/11821801/why-use-a-reentrantlock-if-one-can-use-synchronizedthis) – Anton Vetrov Apr 26 '16 at 10:13