如何在Java中运行轮询阻塞消费者?

如何在Java中运行轮询阻塞消费者?,java,multithreading,concurrency,blocking,java.util.concurrent,Java,Multithreading,Concurrency,Blocking,Java.util.concurrent,我有一些服务,既从入站队列消费,又产生到某个出站队列(其中,由该服务创建的另一个线程拾取消息并将其“传输”到目的地) 目前,我使用了两个普通的线程s,如下面的代码中所示,但我知道,一般来说,您不应该再使用它们,而应该使用更高级别的抽象,如ExecutorService 这对我来说有意义吗?更具体地说,我的意思是-> 它会减少代码吗 使代码在发生故障时更加健壮 允许更平滑的螺纹终止?(这在运行测试时非常有用) 我是不是错过了什么重要的东西?(来自java.util.concurrent的一些其

我有一些服务,既从入站队列消费,又产生到某个出站队列(其中,由该服务创建的另一个线程拾取消息并将其“传输”到目的地)

目前,我使用了两个普通的
线程
s,如下面的代码中所示,但我知道,一般来说,您不应该再使用它们,而应该使用更高级别的抽象,如
ExecutorService

这对我来说有意义吗?更具体地说,我的意思是->

  • 它会减少代码吗
  • 使代码在发生故障时更加健壮
  • 允许更平滑的螺纹终止?(这在运行测试时非常有用)
我是不是错过了什么重要的东西?(来自java.util.concurrent的一些其他类)


对我来说,使用线程池的主要好处来自于在单个、独立且通常较短的作业中构建工作,以及在
ThreadPool
s private
Worker
s中更好地抽象线程。有时,您可能希望更直接地访问这些文件,以了解它们是否仍在运行等。但通常有更好的、以工作为中心的方法来实现这一点

至于处理失败,您可能需要提交自己的
ThreadFactory
来创建带有自定义
UncaughtExceptionHandler
的线程,通常,您的
Runnable
作业也应该提供良好的异常处理,以便记录有关失败的特定作业的更多信息。 让这些作业成为非阻塞作业,因为您不想让阻塞的工作线程填满线程池。在作业排队之前移动阻止操作

通常,
ExecutorService
s提供的
shutdown
shutdownNow
以及作业中的适当中断处理将允许顺利终止作业

// called on service startup
private void init() {
    // prepare everything here
    startInboundWorkerThread();
    startOutboundTransporterWorkerThread();
}

private void startInboundWorkerThread() {
    InboundWorkerThread runnable = injector.getInstance(InboundWorkerThread.class);
    inboundWorkerThread = new Thread(runnable, ownServiceIdentifier);
    inboundWorkerThread.start();
}

// this is the Runnable for the InboundWorkerThread 
// the runnable for the transporter thread looks almost the same
@Override
public void run() {       
    while (true) {
        InboundMessage message = null;
        TransactionStatus transaction = null;

        try {
            try {
                transaction = txManager.getTransaction(new DefaultTransactionDefinition());
            } catch (Exception ex) {
                // logging
                break;
            }

            // blocking consumer
            message = repository.takeOrdered(template, MESSAGE_POLL_TIMEOUT_MILLIS);
            if (message != null) {                   
                handleMessage(message);
                commitTransaction(message, transaction);
            } else {
                commitTransaction(transaction);
            }
        } catch (Exception e) {
            // logging
            rollback(transaction);
        } catch (Throwable e) {
            // logging
            rollback(transaction);
            throw e;
        }

        if (Thread.interrupted()) {
            // logging
            break;
        }
    }

    // logging
}

// called when service is shutdown
// both inbound worker thread and transporter worker thread must be terminated
private void interruptAndJoinWorkerThread(final Thread workerThread) {
    if (workerThread != null && workerThread.isAlive()) {
        workerThread.interrupt();

        try {
            workerThread.join(TimeUnit.SECONDS.toMillis(1));
        } catch (InterruptedException e) {
            // logging
        }
    }
}