这是我的代码被破解
public void testThread() throws Exception {
final List<String> list = new ArrayList<String>();
ExecutorService checkPool = Executors.newFixedThreadPool(100);
for (int i = 1; i <= 100000; i++) {
checkPool.execute(new Runnable() {
public void run() {
list.add("abc");
}
});
}
checkPool.shutdown();
try {
checkPool.awaitTermination(Integer.MAX_VALUE, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i).toString());
}
}
我在junit测试中运行它,但它在
处抛出NullPointerExceptionSystem.out.println(list.get(i).toString());
我不知道为什么会这样!
答案 0 :(得分:2)
当您在add()
上执行list
时,您会遇到竞争条件。
当您运行execute()
时,无法保证Runnable
对象的run()
方法何时会实际运行。
要防止出现这种情况,您需要使用synchronized
关键字来锁定对list
的访问权限:
public void run() {
synchronized (list) {
list.add("abc");
}
}
答案 1 :(得分:1)
因为list.get(i)
可能会返回null
,然后您在.toString()
上致电null
。当您迭代它时,您应该与调试器一起检查list
内的内容。
更具体地说,当您到达i == list.size()
答案 2 :(得分:0)
Native Junit测试方法不支持多线程测试,因为当Junit测试方法完成后会调用System.exit,所以线程将停止。也许这就是你无法从列表中获取字符串的原因。
但您可以使用GroboUntils来测试多线程,下面的一些示例将告诉您如何使用:
@Test
public void MultiRequestsTest() {
TestRunnable runner = new TestRunnable() {
@Override
public void runTest() throws Throwable {
// to write your test case here
}
};
int runnerCount = 100;
TestRunnable[] trs = new TestRunnable[runnerCount];
for (int i = 0; i < runnerCount; i++) {
trs[i] = runner;
}
MultiThreadedTestRunner mttr = new MultiThreadedTestRunner(trs);
try {
mttr.runTestRunnables();
} catch (Throwable e) {
e.printStackTrace();
}
}