为什么这个片段会产生NullPointerException

时间:2014-11-19 01:43:45

标签: java multithreading

这是我的代码被破解

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测试中运行它,但它在

处抛出NullPointerException
System.out.println(list.get(i).toString());    

我不知道为什么会这样!

3 个答案:

答案 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();
    }

}