Задачу решил, поэтому могу прикрепить только часть кода (этого будет достаточно) - метод run() класса Consumer
public void run() {
        try {
            Thread.sleep(450);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        while (!Thread.currentThread().isInterrupted()) {
            ShareItem item = null;
            try {
                System.out.println("take"); // debug
                item = queue.take();
                System.out.format("Processing %s\n", item.toString());
            } catch (InterruptedException e) {
//                break;
                System.out.println("exception caught"); // debug
            }
        }
    }
В методе main вызывается метод interrupt() для объекта класса Consumer и прерывает его работу. После того, как поток был прерван, queue.take() из строки 11 кидает InterruptException и, допустим, ни как не обрабатывается в блоке catch. Далее начинается с начала цикл
while(!Thread.currentThread().isInterrupted()) { ... }
из которого программа должна сразу же выйти, потому что поток прерван и должно сработать условие цикла, но этого не происходит! Причем на этот раз queue.take() не кидает исключения, а просто зависает. Почему так происходит и как после этого доверять методу isInterrupted()?