如何在匿名thread子类中保证线程安全

在做性能测试的过程中,我写了两个虚拟类 ThreadLimitTimeCountThreadLimitTimesCount 做框架,通过对线程的标记来完成超时请求的记录。旧方法如下:

@Override
    protected void after() {
        requestMark.addAll(marks);
        marks = new ArrayList<>();
        GCThread.stop();
        synchronized (this.getClass()) {
            if (countDownLatch.getCount() == 0 && requestMark.size() != 0) {
                Save.saveStringList(requestMark, MARK_Path.replace(LONG_Path, EMPTY) + Time.getDate().replace(SPACE_1, CONNECTOR));
                requestMark = new Vector<>();
            }
        }
    }

其中我用了 synchronized 关键字同步,但是在匿名类的单元测试中出现一个BUG,匿名类中没有实现 clone() 方法,也不能直接使用深拷贝方法,导致无法直接复制对象,所以我创建了多个功能相同的匿名线程类。问题来了,在代码执行过程中,偶然会出现记录 markrequest 的文档中出现空内容的形式。

我查询了一些资料,感觉问题出现在 synchronized (this.getClass()) 这个问题了,因为我打印 this.getClass() 给我的是当前测试类的类名,感觉原因就是匿名类的问题,匿名类相当于多个实现类, synchronized (this.getClass()) 无法保证多各类对象同时访问这个方法的线程安全。最终,我选择了另外一种方式,就是单独写一个线程安全的 save() 方法,这样就可以保证所有访问保存方法的线程的安全,将清空记录列表的功能也放在了这个线程安全的方法里了。

/**
     * 同步save数据,用于匿名类多线程保存测试数据
     *
     * @param data
     * @param name
     */
    public static void saveStringListSync(Collection<String> data, String name) {
        synchronized (Save.class) {
            if (data.isEmpty()) return;
            saveStringList(data, name);
        }
    }

原来虚拟类的方法就变成了如下的样子:

if (countDownLatch.getCount() == 0 && requestMark.size() != 0) {
                Save.saveStringListSync(requestMark, MARK_Path.replace(LONG_Path, EMPTY) + Time.getDate().replace(SPACE_1, CONNECTOR));
            }
  • 郑重声明 :文章首发于公众号“FunTester”,禁止第三方(腾讯云除外)转载、发表。
我来评几句
登录后评论

已发表评论数()

相关站点

热门文章