简体   繁体   English

具有多线程的Collection.sort()中的NullpointerException

[英]NullpointerException in Collection.sort() with multithreading

I have a class that should test my Fibonacci function using multithreading 我有一个应该使用多线程测试我的斐波那契函数的类

public class PerformanceTesterImpl implements PerformanceTester{
    public static List<Long> executionTimesList = new ArrayList();
    public static List<Runnable> tasksList = new ArrayList();
    public int fib;
    public PerformanceTestResult performanceTestResult;

    @Override
    public PerformanceTestResult runPerformanceTest(Runnable task, int calculationCount, int threadPoolSize) {

        for(int i=0; i<calculationCount; i++){
            tasksList.add(createTask(fib));
        }

        ExecutorService executor = Executors.newFixedThreadPool(threadPoolSize);
        for(Runnable r : tasksList){
            executor.execute(r);
        }
        executor.shutdown();  

        try {
            executor.awaitTermination(1, TimeUnit.MINUTES);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // Here all threads should complete all work. Is it OK?
        mapValues();
        return performanceTestResult;
    }

    private PerformanceTestResult mapValues(){
        Collections.sort(executionTimesList);
        performanceTestResult = new PerformanceTestResult(getSum(executionTimesList), (Long)executionTimesList.get(0), (Long)executionTimesList.get(executionTimesList.size()-1));
        return performanceTestResult;
    }


    public  Runnable createTask (final int n) {
        fib = n;
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                long startTime = System.currentTimeMillis();
                FibCalc fibCalc = new FibCalcImpl();
                fibCalc.fib(n);
                long executionTime = System.currentTimeMillis() - startTime;
                executionTimesList.add(executionTime);
            }
        };
        return runnable;
    }


    private static long getSum(List<Long> executionTimes){
        long sum = 0;
        for(long l : executionTimes){
            sum += l;
        }
        return sum;
    }
}

but from time to time NULL appears in my collection and when I'm trying to sort executionTimeList I receive NullpointerException. 但是有时我的集合中会出现NULL,并且当我尝试对executeTimeList进行排序时,会收到NullpointerException。 I think there is a problem with executing threads. 我认为执行线程有问题。 What should I do to correct this exception? 我该怎么做才能纠正此异常?

ArrayList is not thread safe. ArrayList不是线程安全的。

From the Javadoc : 从Javadoc:

 * If multiple threads access an <tt>ArrayList</tt> instance concurrently,
 * and at least one of the threads modifies the list structurally, it
 * <i>must</i> be synchronized externally.  (A structural modification is
 * any operation that adds or deletes one or more elements, or explicitly
 * resizes the backing array; merely setting the value of an element is not
 * a structural modification.)  This is typically accomplished by
 * synchronizing on some object that naturally encapsulates the list.

 * If no such object exists, the list should be "wrapped" using the
 * {@link Collections#synchronizedList Collections.synchronizedList}
 * method.  This is best done at creation time, to prevent accidental
 * unsynchronized access to the list:<pre>
 *   List list = Collections.synchronizedList(new ArrayList(...));</pre>

When you call add from multiple threads, the ArrayList may be in inconsistent state.You should synchronize access to it. 当您从多个线程调用add ,ArrayList可能处于不一致状态。您应该同步对其的访问。

Try : 尝试:

        public void run() {
            long startTime = System.currentTimeMillis();
            FibCalc fibCalc = new FibCalcImpl();
            fibCalc.fib(n);
            long executionTime = System.currentTimeMillis() - startTime;
            synchronized (this) {
                executionTimesList.add(executionTime);
            }
        }

executionTimesList is shared among all threads. 执行时间列表在所有线程之间共享。 They run in concurrence in your code with no synchronization. 它们在您的代码中并发运行,没有同步。 So it's logical that any inconsistency state appears if a thread works on the list and has not finished its job and the cpu gives the priority to another thread which works on the list too, the first thread will be in a inconsistent state when it will be restarted. 因此,如果一个线程在该列表上工作并且尚未完成其工作,并且cpu将优先级也赋予在该列表上工作的另一个线程,则出现任何不一致状态是合乎逻辑的,当第一个线程处于该状态时,它将处于不一致状态重新启动。 You must synchronize the access for the static field executionTimesList 您必须同步对静态字段executionTimesList的访问

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM