0

I'm trying to remove elements manually from ArrayBlockingQueue by using the removeIf() method, using threads. And then have another thread trying to put an element into the ArrayBlockingQueue. It doesn't work, which is weird because I thought that put() tries and tries until there's space and puts an element in successfully or is my understanding of it wrong?

What's the problem and what should I do to work around this problem?

Here's my code

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.CyclicBarrier;


class HelloWorld {
    
    static ArrayBlockingQueue<Integer> q = new ArrayBlockingQueue(2);
    static CyclicBarrier cb = new CyclicBarrier(2);

    public static void main(String[] args) {
        try {
            Thread t1 = new Thread(() -> {
                try {
                    q.put(2);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            });
            Thread t2 = new Thread(() -> {
                try {
                    q.put(2);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            });
            Thread t3 = new Thread(() -> {
                try {
                    q.put(1);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            });
            t1.start();
            t2.start();
            t3.start();
            t1.join();
            t2.join();
            System.out.println(q.size());
            q.removeIf(ii -> ii == 2);
            System.out.println(q.size());
            t3.join();
            System.out.println(q.size());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

The first output was 2, second was 0 after the removeIf() method and the third output never arrived, I think its because the put() method was never triggered. I expected the third output to be 1 as I thought the put() method will be triggered as space was vacated using removeIf(), but the third output never came no matter how long I waited

  • 1
    Never write empty catch blocks. Always log or rethrow the exception, if you must catch it. – tgdavies Nov 30 '22 at 23:03
  • 1
    Threads execute asynchronously. That means the two threads you created may not have completed yet, or even started executing. If you need to test this, you should use some signal (like a [CountDownLatch](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/concurrent/CountDownLatch.html) or `.join()`) so you can execute after they're done. – markspace Nov 30 '22 at 23:04
  • Please show a complete, runnable example. – tgdavies Nov 30 '22 at 23:05
  • @markspace ah sorry it wasn't shown in the code above but I used CyclicBarrier to wait for the thread to finish before printing q.size() – Jia Wen Chin Nov 30 '22 at 23:31
  • @tgdavies I see, alright I have now added in suitable code to not make it empty – Jia Wen Chin Nov 30 '22 at 23:36
  • @tgdavies I have now included the code for the whole file – Jia Wen Chin Nov 30 '22 at 23:36
  • As your `CyclicBarrier` is waiting for one thread, await will return as soon as your main thread calls `await`, i.e. before your other threads have completed. You need to wait for 4 threads and call `await` from your other threads. – tgdavies Nov 30 '22 at 23:41
  • @tgdavies hey sorry I can't quite follow, do you mean I should set the parameter for CyclicBarrier to 4? – Jia Wen Chin Nov 30 '22 at 23:46
  • Your `CyclicBarrier` doesn't know about the other threads -- and they don't know about it. Read the Javadoc for `CyclicBarrier`. – tgdavies Dec 01 '22 at 00:22
  • @tgdavies understood, I've now made changes so as to not use CyclicBarrier but used Thread.join() instead, however the third output never arrives, even after t3.join() does that mean removeIf() does not trigger the put() method? – Jia Wen Chin Dec 01 '22 at 01:01
  • Have a look at the source code of `ArrayBlockingQueue`. Look at the `Condition` `put` waits on, look at where it gets signalled. Will it get signalled by `removeIf`? – tgdavies Dec 01 '22 at 01:09
  • ohh, it doesn't get signalled by removeIf, but in that case, is there a work around to this? – Jia Wen Chin Dec 01 '22 at 01:12
  • Iterate queue and use ```remove``` method? – zysaaa Dec 01 '22 at 02:56

0 Answers0