【问题标题】:How do i unit test the following lock and multi-threaded code我如何对以下锁和多线程代码进行单元测试
【发布时间】:2015-06-28 00:49:02
【问题描述】:

我有以下使用 gson 将数据写入文件的写入方法。

private static final File CONFIG_FILE = new File("./config.json");; 
private static final ReadWriteLock READ_WRITE_LOCK = new ReentrantReadWriteLock(true);
private static final Lock READ_LOCK = READ_WRITE_LOCK.readLock();
private static final Lock WRITE_LOCK = READ_WRITE_LOCK.writeLock();
...
    public void write(JsonData data) {
    Verifier.verifyNotNull(data,"data : null");
    Verifier.verifyNotNull(data.getData(),"JsonData data : null");
    Verifier.verifyNotEmpty(data.getIdentifier(),"JsonData identifier : empty");

    Writer writer  = null;
    Gson gson = null;
      try {  
         WRITE_LOCK.lock();
         writer = new FileWriter(CONFIG_FILE);

         gson = new GsonBuilder().setPrettyPrinting().create();
         gson.toJson(data, writer);
      } 
      catch (IOException e) {  
           e.printStackTrace();  
      }  
      finally {
         try {
             if (writer != null) {
                 writer.flush();
                 writer.close();
             }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }  
       catch (RuntimeException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }  
        finally {
           WRITE_LOCK.unlock();
        }
      }

上面显示的锁是Java库提供的可重入锁。如果我想对上述线程安全方法进行单元测试,如何测试呢?

请指教,

谢谢!

【问题讨论】:

  • 为此您需要多个尝试块。如果writer.flush()抛出异常,你不会释放锁。
  • 您好,感谢您的关注。我将“writer.flush()”移到了 catch 块。由于“.flush”和“.close”方法都抛出“IOExceptions”,我认为锁定将在上面显示的“IOException”的 catch 块中释放。编辑代码
  • 尝试嵌套你的 try 块,这样你的外部块就只用于锁。这避免了不得不在不同的地方调用 unlock 或对 flush() 中的错误感到惊讶,抛出您错过的 RuntimeException
  • 如果我只是将释放锁移动到 finally 块怎么样。然后在上面的代码中为 close 和 flush 捕获 IOException 和 RuntimeException(无需嵌套 try-catch)。编辑了代码。这行得通吗?
  • 如果你没有说明代码的规范,没有人可以建议如何测试代码是否符合规范。

标签: java multithreading unit-testing jmock


【解决方案1】:

如果您注入 WriterGson 对象,您可以提供一个模拟实现。如果你嘲笑作者,让write 方法阻塞,这样它们就不会完成并释放锁。在一个线程中执行此操作。在另一个中,再次调用 your write 方法。最后,在您的“主”测试线程中,旋转直到阻塞线程的状态为Thread.State.BLOCKED。如果它从未被阻止或完成,你就失败了。一旦你看到它被阻塞,释放第一个线程(CountDownLatch 很适合这个),并验证两个线程都完成了。

【讨论】:

  • 感谢您的评论,我正在查看 Jmock 提供的 Blitzer 类。这也够了吗? jmock.org/threading-blitzer.html
  • 这取决于您锁定的原因。如果是因为 Gson 不是线程安全的,那么可能。如果是因为您不想同时写入文件,则更多取决于您的操作系统和文件锁定。
  • 我正在锁定,以便一次只能写入一个线程。基本上是读写器问题。这是一个配置文件,所以我不希望多个线程争夺写入它。
  • 避免这个问题的一种方法是让一个线程负责编写配置文件,然后其他线程将它们的更改排队。消息传递是使事情线程安全的一个好技巧。
猜你喜欢
  • 2010-09-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多