惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Cisco Talos Blog
Cisco Talos Blog
阮一峰的网络日志
阮一峰的网络日志
云风的 BLOG
云风的 BLOG
D
Docker
Vercel News
Vercel News
IT之家
IT之家
Recent Announcements
Recent Announcements
Last Week in AI
Last Week in AI
V
Visual Studio Blog
Engineering at Meta
Engineering at Meta
腾讯CDC
Google DeepMind News
Google DeepMind News
I
InfoQ
博客园 - 三生石上(FineUI控件)
Apple Machine Learning Research
Apple Machine Learning Research
The GitHub Blog
The GitHub Blog
博客园 - Franky
The Cloudflare Blog
A
About on SuperTechFans
有赞技术团队
有赞技术团队
Y
Y Combinator Blog
T
Tenable Blog
P
Proofpoint News Feed
Recorded Future
Recorded Future
Security Latest
Security Latest
H
Hackread – Cybersecurity News, Data Breaches, AI and More
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
博客园 - 聂微东
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Google Online Security Blog
Google Online Security Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Simon Willison's Weblog
Simon Willison's Weblog
The Last Watchdog
The Last Watchdog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
N
News and Events Feed by Topic
TaoSecurity Blog
TaoSecurity Blog
U
Unit 42
The Hacker News
The Hacker News
Martin Fowler
Martin Fowler
T
Threat Research - Cisco Blogs
NISL@THU
NISL@THU
F
Full Disclosure
M
MIT News - Artificial intelligence
人人都是产品经理
人人都是产品经理
Hugging Face - Blog
Hugging Face - Blog
V
V2EX
Project Zero
Project Zero

博客园 - 三颗纽扣

windows下安装redmine-2.1 try-cache-finally 在线程被杀掉时还有作用吗? 使用InfoBright实现20-100亿条原始话单记录的检索 Hibernate乐观锁真的会抛出异常吗? 并非文学化编程,在VS环境下的折中方案 快速复制NuGet引用 语义版本规范 基础框架的基础组件 在 IIS 6 上架设 NuGet Server DotNet开发利器之MyEclipseShortcuts 通过 POI 获取图片在 Excel 表格中的位置 我们是原始生物 没有别的,只有天使 灯是用来照亮的,而不是引路的 戒了,过去完成时 我送给你们的,没有别的——只有天使。 Builder 链——另类一点的Builder模式 控制内存的使用之二:对象缓存 pool and cache 控制内存的使用
多线程JUnit单元测试:GroboUtils and ConTest
三颗纽扣 · 2010-03-22 · via 博客园 - 三颗纽扣

“并行程序易于产生 bug 不是什么秘密。编写这种程序是一种挑战,并且在编程过程中悄悄产生的 bug 不容易被发现。许多并行 bug 只有在系统测试、功能测试时才能被发现或由用户发现。到那时修复它们需要高昂的费用 -- 假设能够修复它们 -- 因为它们是如此难于调试。”以上论述来自IBM论坛中关于 ConTest 的一篇介绍文章,并且,我还要补充一点,这种 BUG 通常根本无法重现,以至于要找到发生 BUG 的原因都是非常的困难;即使幸运的找到了可能原因,修改了代码,要确认问题确实得到了解决,依然是非常的困难,因为根本无法进行有效的测试。

JUnit提供了很好的单元测试框架,但是对于多线程的并发测试,却无能为力。经过一番搜索,找到了一个叫 GroboUtils 的东西,关于它的介绍不少,这里不再重复,GroboUtils 解决了启动多线程以及当某个线程出错时将错误返回给 JUnit 的问题,现在我们可以比较简单启动多个线程并验证结果了。具体介绍请自己 google 一下,我这里简单的贴一个 Demo 代码,当然和官方以及一般的例子不同,我比较喜欢使用内部匿名类来启动线程。这个测试很简单,启动 5 个线程,并发的进行 i++ 运算,我有意的注释掉了同步代码,这样应该会导致最后测试无法通过。

class ParalInc {
    
public int i=0;    
}
public class ParalIncTest {public static class Incrementor extends Thread {
       
public void run() {
       }
    }

    @Test

public void testInc() throws Throwable {
        
for (int i = 0; i < 1000; i++) {
            
final ParalInc target = new ParalInc();
            
            TestRunnable r 
= new TestRunnable() {
                
public void runTest() throws Throwable {
//                synchronized(ParalIncTest.class) {
                    target.i++;
//                }
                }
            };
            
            TestRunnable[] tcs 
= {r, r, r, r, r};
            
int threadCount = tcs.length;
            
            MultiThreadedTestRunner mttr 
= new MultiThreadedTestRunner( tcs );
            mttr.runTestRunnables( 
2 * 60 * 1000 );
            
            System.out.println(
"final value: " + target.i);
            
            
if (target.i != threadCount) {
                System.err.println(
"   Bug - at loop " + i);
            }
            
            assertEquals(threadCount, target.i);
        }
    }
}

开始的时候我并没有添加最外层循环,然而测试的结果很遗憾,怎么都无法让这段代码出错。加上循环以后,才偶尔会出错,也一般要循环到数百次以后才会发生错误。导致这种结果的原因,估计是线程的切换其实并发象我们想象的那么频繁,而且要恰恰在共享冲突点发生切换,这个概率也确实非常的小。如果能够控制虚拟机的线程切换,使得共享冲突概率更大一些那该是多么好啊。

因此,我找到了这篇文章 http://www.ibm.com/developerworks/cn/java/j-contest.html ,ConTest,这真是个好东西啊,配置好以后,还是上面那段测试代码,但是测试结果几乎都会检测到冲突,而且通常是在循环了2-3次后就检测到了。

ConTest 下载链接在从上面的文章中可直接找到,可以用 Eclipse plug-in 方式安装,update 地址 http://awwebx04.alphaworks.ibm.com/ettktechnologies/updates 。但是我实在没发现它给 Eclipse 添加了什么功能,其实我觉得主要还是只要下载到那个 ZIP 包就可以了,并不需要安装为 plug-in。

下载下来以后,ConTest 并不能自动的开始工作,需要一点点配置工作,这有点烦人。

首先要将 ConTest.jar 包拷贝到一个便于指定位置的地方,我一般倾向于将它放在工程目录的lib子目录下,另外 ZIP 包的 LIB 目录下还有一个 KingProperties 文件,要拷贝到和 ConTest.jar 相同的目录中。修改 KingProperties 文件,当然也可以不改,我主要是修改 output 目录,为 output = target,和 maven 保持一致,一切都输出到那里去。

这还只是一些准备活动,最后,要让 ConTest 开始工作,还需要修改 Run|RunConfigurations,在单元测试的 jvm 启动参数中指定启动 ConTest , 既添加 JVM 参数:

-javaagent:lib/ConTest.jar -Dcontest.targetClasses=demo/ParalIncTest

这里 -Dcontest.targetClasses=demo/ParalIncTest 既指定要进行并行性分析的类名,可以用逗号分隔指定多个类,当然这个参数本身也可以 KingProperties 文件中指定的,但是我觉得在命令行测试比较方便一些,毕竟从单元测试的角度来说,一次应该只测试一个类。在命令行测试,就不需要多套 KingProperties 配置文件。

至此,所有配置工作完成,依然像以前一样启动单元测试,ConTest 作为 javaagent 装载,因此它其实是在 ClassLoader 加载类字节码的时候介入,修改字节码在其中加入一些线程切换的代码,这样线程切换更频繁了,特别在一些同步块中,发生同步冲突的概率自然就大很多了。

总的来说,将 GroboUtils 和 ConTest 结合起来使用,效果还是相当不错的,并发测试变得简单多了,而且检测到冲突的可能性非常的大。