当前位置: 首页 > 知识库问答 >
问题:

TreeMap中的此空指针异常是由于并发访问引起的吗?

屈昊天
2023-03-14

我知道TreeMap不是线程安全的。我正在尝试对TreeMap和ConcurrentSkipListMap进行比较。我使用的代码如下所示,我想确定我得到的错误是否是TreeMap不是线程安全的,而不是因为其他原因。

线程“Pool-1-Thread-52”中的异常java.lang.NullPointerException在java.util.TreeMap.RotateLeft(TreeMap.java:2060)在java.util.TreeMap.FixAfterInsertion(TreeMap.java:2127)在java.util.TreeMap.Put(TreeMap.java:574)在ThreadTestTreeMap$1.Run(ThreadTestTreeMap.Put(TreeMap.java:39)在

import com.google.common.collect.Ordering;
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.ConcurrentSkipListMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class ThreadTestTreeMap {
    public static Map<String, Object> map;
    public static int THREADS =  100;
    public static long averageTime = 0;

public static void main(String args[]) throws InterruptedException {
    for (int i = 0; i < 1; i++) {
        map = new TreeMap<>(Ordering.natural());
//            map = new ConcurrentSkipListMap<>(Ordering.natural());

        long time = System.nanoTime();
        ExecutorService service = Executors.newFixedThreadPool(THREADS);

        for (int j = 0; j < THREADS; j++) {
            final int finalJ = j;
            service.execute(new Runnable() {
                public void run() {
                    try {
                        Thread.sleep(THREADS - finalJ);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    long threadId = Thread.currentThread().getId();
                    map.put("tag"+threadId, "hello");
            }});
        }
        service.shutdown();
        service.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
        long timeUsed = (System.nanoTime() - time) / 1000000L;
        averageTime += timeUsed;
        System.out.println("All threads are completed in "
                + timeUsed + " ms");
    }
    System.out.println("The average time is " + averageTime / 10 + " ms");
}
}

共有1个答案

冯枫
2023-03-14

无论NullPointerException是否是并发修改的直接结果,它都在TreeMap的Javadoc中声明:

请注意,此实现不是同步的。如果多个线程并发访问一个映射,并且其中至少一个线程在结构上修改了该映射,则必须在外部对其进行同步。

当您在多个线程中修改映射而不进行同步时,您没有按预期使用的方式使用类。

添加外部同步:)

 类似资料:
  • 让我们考虑一个<代码>父< /代码>类,它只包含一个<代码>整数< /代码>属性。我用一个空变量创建了6个父类对象。然后我将这些对象添加到列表中。 我想通过属性的值检索相应的对象。我使用了Java8流。 但是我得到了,所以我编辑了代码: 但是如果任何对象为null,我想抛出一个异常。如果列表中没有对象为null,那么我想从列表中检索相应的对象。 如何使用Java 8 Streams使用一条语句实现

  • 第一个示例:“源代码”https://ci.apache.org/projects/flink/flink-docs-stable/dev/stream/operators/process_function.html“” 我正在尝试重写KeyedProcessFunction类的processElement()。ProcessElement有3个参数,其中一个参数是上下文对象。当我试图从上下文对象

  • 我正在尝试通过Maven运行cucumber+testng+selenium。 当我在Eclipse中通过TestNG测试运行它时,它工作得很好,但当我使用mvn测试时,它会抛出空指针异常 我是不是漏掉了什么?

  • 它是从哪里来的?

  • 当我们尝试用Null值获取数据时 IN子句获得空指针异常。 也许是因为这个。 在数据库中,我们可以提供null in IN子句。 jooq中存在一个“无法修复”的问题https://github.com/jOOQ/jOOQ/issues/3867 有一些替代方案: 在输入前检查null(在我的情况下,这是一个非常大的select语句) 所以如果我想让这成为可能,还有其他的解决方法吗。 注:类似的情