当前位置: 首页 > 面试题库 >

有什么好的方法可以测试Java方法是否已同步?

邢雨华
2023-03-14
问题内容

我有几个实现某些接口的类。该接口有一个约定,某些方法应该同步,有些方法应该不同步,我想通过单元测试对所有实现进行验证。这些方法应使用synced关键字或将其锁定this-与SynchronizedCollection()包装器非常相似。这意味着我应该能够从外部观察它。

如果我有一个调用iterator()的线程来继续Collections.synchronizedCollection()的示例,我仍然应该能够使用另一个线程进入add()之类的方法,因为iterator()不应进行任何锁定。另一方面,我应该能够在集合上进行外部同步,并看到另一个线程在add()上阻塞。

有没有很好的方法来测试方法是否在JUnit测试中同步? 我想避免长时间睡眠的陈述。


问题答案:

非常感谢Zwei steinen编写了我使用的方法。我处理过的示例代码中存在一些问题,因此我认为值得在这里发表我的发现。

  • 对join()的调用期望以毫秒为单位,而不是纳秒。
  • 这两个线程必须协调,否则尝试线程可以在更衣室线程获取锁之前开始和结束所有线程。
  • 直到我们记录了开始时间之后,才应该开始尝试线程。否则,该线程将获得足够的领先优势,以至于记录的时间可能比超时时间稍短,从而导致虚假故障。

这是作为Scala特性的同步测试代码:

trait SynchronizedTestTrait
{
    val classUnderTest: AnyRef

    class Gate
    {
        val latch = new java.util.concurrent.CountDownLatch(1)

        def open()
        {
            this.latch.countDown
        }

        def await()
        {
            this.latch.await
        }
    }

    def nanoTime(code: => Unit) =
    {
        val before = System.nanoTime
        code
        val after = System.nanoTime
        after - before
    }

    def assertSynchronized(code: => Unit)
    {
        this.assertThreadSafety(threadSafe = true, millisTimeout = 10L)(code)
    }

    def assertNotSynchronized(code: => Unit)
    {
        this.assertThreadSafety(threadSafe = false, millisTimeout = 60L * 1000L)(code)
    }

    def assertThreadSafety(threadSafe: Boolean, millisTimeout: Long)(code: => Unit)
    {
        def spawn(code: => Unit) =
        {
            val result = new Thread
            {
                override def run = code
            }
            result.start()
            result
        }

        val gate = new Gate

        val lockHolderThread = spawn
        {
            this.classUnderTest.synchronized
            {
                // Don't let the other thread start until we've got the lock
                gate.open()

                // Hold the lock until interruption
                try
                {
                    Thread.sleep(java.lang.Long.MAX_VALUE)
                }
                catch
                {
                    case ignore: InterruptedException => return;
                }
            }
        }

        val measuredNanoTime = nanoTime
        {
            // Don't start until the other thread is synchronized on classUnderTest
            gate.await()
            spawn(code).join(millisTimeout, 0)
        }

        val nanoTimeout = millisTimeout * 1000L * 1000L

        Assert.assertEquals(
            "Measured " + measuredNanoTime + " ns but timeout was " + nanoTimeout + " ns.",
            threadSafe,
            measuredNanoTime > nanoTimeout)

        lockHolderThread.interrupt
        lockHolderThread.join
    }
}

现在,我们要测试一个简单的类:

class MySynchronized
{
    def synch = this.synchronized{}
    def unsynch = {}
}

测试看起来是这样的:

class MySynchronizedTest extends SynchronizedTestTrait
{
    val classUnderTest = new MySynchronized


    @Test
    def synch_is_synchronized
    {
        this.assertSynchronized
        {
            this.classUnderTest.synch
        }
    }

    @Test
    def unsynch_not_synchronized
    {
        this.assertNotSynchronized
        {
            this.classUnderTest.unsynch
        }
    }
}


 类似资料:
  • 问题内容: 我有一个使用XML和反射将 s 返回到另一个类的类。 通常,这些对象是外部对象的子字段,但有时我想即时生成它。我已经尝试过类似的方法,但无济于事。我相信这是因为Java不允许你访问进行反射的方法。 如果提供的方法失败,则失败。我可以通过制作方法来解决它,或者制作另一个类来派生它。 长话短说,我只是想知道是否存在一种通过反射访问方法的方法。 问题答案: 你可以使用反射调用私有方法。修改已

  • 问题内容: 我必须为我的OJT公司编程一个应用程序管理系统。前端将在C#中完成,后端将在SQL中完成。 现在,我从来没有做过这样的项目。在学校里,我们只有关于SQL的基本课程。不知何故,我们的老师完全没有讨论SQL注入,而我直到现在才通过网上阅读与之接触。 所以无论如何,我的问题是:如何防止C#中的SQL注入?我模糊地认为,可以通过适当地屏蔽应用程序的文本字段来做到这一点,以使其仅接受指定格式的输

  • 对于Mockito和其他测试框架,通常有方法在测试类中模拟方法的功能。我似乎无法让ScalaMock接受同样的方式。 在测试课上,我是: 我知道,如果你嘲笑/剔除类,然后在真实实例上调用相同的功能,这是行不通的。但是有一些变通方法,可以使用模拟调用等。 如果这是错误的方法,测试在同一个测试类中使用其他方法的方法的最佳方法是什么?我认为解耦方法是最好的实践。 谢谢

  • 材料设计非常强调“纸张”的隐喻。要做到这一点,阴影是必不可少的。由于材料设计是一种理念,而不是API(尽管它内置在L中),因此应该在任何地方(Windows窗体、HTML/CSS等)进行设计。如何在Android API 14到20中做到这一点? 请注意,对于圆形和其他非方形形状,预制PNG实际上并不实用。

  • 本文向大家介绍什么是白盒测试,有几种方法相关面试题,主要包含被问及什么是白盒测试,有几种方法时的应答技巧和注意事项,需要的朋友参考一下 又称为逻辑驱动测试,结构测试。知道产品内部的工作过程,可通过测试来检测产品内部动作是否按照规格说明书的规定正常进行,按照程序内部的结构测试程序,检验程序中的每条通路是否都有能按预定要求正确工作,而不顾它的功能。 主要方法:逻辑驱动测试、基路测试 白盒测试分为静态和

  • 在传递给的方法的lambda中,我验证是否使用预期值调用了方法: 由于方法抛出一个,我被迫在lambda内部的调用周围添加一个无用的try/catch块。这是不必要的冗长。 我怎么能避免呢?