java - 要在异步调用上实现优雅的关闭检查锁定,还是要处理异常?

标签 java multithreading asynchronous locking shutdown

我正在开发一个 Java 应用程序,它在大部分时间(包括关闭点)都必须处理来自外部框架的大量传入异步调用。在正常操作期间,这些传入调用需要再次异步地分派(dispatch)到另一个框架。

目前,我正在让我的模块成为一个“好”公民,并围绕关闭标志进行一些锁定,一旦设置该标志,将优雅地停止发送任何进一步的传出调用。

麻烦的是,因为传入和传出调用都是异步的,我不得不让每个“工作”任务执行两组锁定(见下文)以执行相同的关闭标志检查(编辑:有人在另一个问题中向我指出,使用信号量每个 worker 只需要一次获取/释放)。它可以工作,但是有许多这样的工作任务需要处理,我担心性能会逐渐下降。一旦框架稍有扩展,分析将很快出现,但无论结果如何,遵循最佳实践都是好的。

另一种方法是简单地不执行关闭标志检查锁定,并处理在异步调用完成处理之前关闭外部框架时生成的预期异常。我应该补充一点,如果采用这种方法,不会对运营产生不利影响。这两种方法都会导致干净关闭。

请问您认为哪种做法更好?无一异常(exception)的严厉锁定,与没有锁定但一连串的异常(exception)相比较。

有了锁,worker 任务代码看起来像这样:

final private ReentrantReadWriteLock shutdownLock = new ReentrantReadWriteLock();
private boolean isShutdown;

private void workerTask()
{
   try
   {
      shutdownLock.readLock().lock();

      if (isShutdown)
         return;

      executeAsynchronously(new Runnable()
      {
         @Override
         final public void run()
         {
            try
            {
               shutdownLock.readLock().lock();

               if (isShutdown)
                  return;

               // Do something here.
            }
            finally
            {
               shutdownLock.readLock().unlock();
            }
         }
      });
   }
   finally
   {
      shutdownLock.readLock().unlock();
   }
}

shutdown 方法请求 shutdownLock.writeLock(),然后设置 isShutdown 标志。

没有锁定和预期关闭产生的异常的替代方案看起来像这样:

volatile private boolean isShutdown;

private void workerTask()
{
   try
   {
      executeAsynchronously(new Runnable()
      {
         @Override
         final public void run()
         {
            try
            {
               // Do something here.
            }
            catch (final FrameworkRuntimeException exception)
            {
               if ((! isShutdown) || (exception.type != 
                                      FrameworkRuntimeException.FrameworkIsDisposed))
                  throw exception;
            }
         }
      });
   }
   catch (final FrameworkRuntimeException exception)
   {
      if ((! isShutdown) || (exception.type != 
                             FrameworkRuntimeException.FrameworkIsDisposed))
         throw exception;
   }
}

此实现的关闭方法将 volatile isShutdown 标志设置为 true。

提前感谢您的任何反馈,

俄罗斯人

编辑:有人在另一个问题中向我指出,我可以使用信号量来避免第一种方法中的双重锁定,所以它毕竟不会那么笨拙, 但问题仍然存在。

最佳答案

一般来说,我更喜欢先检查是否关闭,然后执行任务的方法。如果您乐观地丢弃您“知道”是由于关闭而导致的异常,那么您将面临错误分类错误并错过真正问题的风险。

就简化代码而言,您可以摆脱所有锁定,只需确保您的 executeAsynchronously 方法使用 ExecutorService - 然后是您的 shutdown 方法只是调用服务上的 shutdown,如果 isShutdown 返回 true 并且如果您需要等待任务完成再返回,则可以跳过任务创建可以使用有用的 awaitTermination 方法。

关于java - 要在异步调用上实现优雅的关闭检查锁定,还是要处理异常?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6934484/

相关文章:

scala - 选择正确的 ExecutionContext

java - toString() 方法和使用 ( +"") 之间的区别

Java HttpClient 和设计身份验证问题

java - 以定时任务方式运行JAVA程序

Java SwingUtilities.invokeLater 更新 TextArea

c# - 我需要每天花好几个小时尽可能快地发送大量 Web 请求。什么是最有效的方法?

java - 自包含 .jar 时启动画面不工作

c# - 使 [IsOneWay=true] WCF 服务异步与在客户端使用任务调用同步方法之间是否存在显着差异?

multithreading - struts Action 单例

objective-c - Objective-C 中的异步调用