由于BlockingQueue的消费者(我认为是在另一个线程上),主线程挂起

时间:2016-11-10 18:48:06

标签: java multithreading blockingqueue

我有一个阻塞的测试(第一个代码块)。我有几个元素都在一起工作。我有一个阻塞队列,我将事件放在其上,然后我有一个消费者将它们关闭并将它们发送到Amazon Kinesis。我很确定我的测试被阻止了,因为队列阻塞了我的消费者,即使我认为它是在一个单独的线程上运行。

// Test.java
@Test
public void testWhileLoop() throws InterruptedException {
    ArrayBlockingQueue<Event> testQ = new ArrayBlockingQueue<Event>(1024);
    // mockKinesis is a mock at the class level.
    KPLPoster kpl = new KPLPoster("TestStream", mockKinesis, testQ);
    Event event = new Event("TestMessage", "TestPartition");
    ListenableFuture<UserRecordResult> fakeReturn = Mockito.mock(ListenableFuture.class);

    final AtomicInteger numberOfWhileLoops = new AtomicInteger();

    Mockito.doAnswer(invocation -> {
        numberOfWhileLoops.incrementAndGet();
        return fakeReturn;
    })
    .when(mockKinesis)
    .addUserRecord("TestStream", "TestPartition", ByteBuffer.wrap("TestMessage".getBytes()));

    kpl.run(); // Hangs here

    for(int i = 100; i > 0; i--){
        testQ.put(event);
    }

    kpl.stop();
    kpl = null;

    assert(numberOfWhileLoops.toString()).equals("100");
}

这是我的KPLPoster继承的BaseKinesisPoster的run方法。应该注意的是,BaseKinesisPoster实现了Runnable接口。

//BaseKinesisPoster.java
@Override
public void run() {
    shutdown = false;
    while (!shutdown && !(Thread.currentThread().isInterrupted())) {
        try {
            this.runOnce();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

最后,这是我的KPLPoster(扩展BaseKinesisPoster)相关runOnce()方法的一部分。

// KPLPoster.java
@Override
protected void runOnce() throws Exception {
    Event event = inputQueue.take();
    //other stuff in my method
}

如何确保阻止我的队列使用者阻止我的测试/主线程?

1 个答案:

答案 0 :(得分:4)

致电时

Thread.run();

它调用调用的方法。没有什么特别的,并且该方法在当前线程中运行。

致电时

Thread.start();

这将启动该线程,该线程又在该新线程中调用run()。

BTW Thread.stop()将在Java 8中抛出UnsupportedOperationException。您不应该使用它。你应该让它自然地完成。