java - 在 Java 中使用线程安全集合时,处理并发问题的最佳方法是什么?

标签 java multithreading concurrency

这对我来说可能非常天真,但我总是假设下面的代码示例在 Java 中使用线程安全集合时始终有效,并且不会因 NullPointerException 而崩溃。不幸的是,线程 t2 似乎能够在调用两个线程声明下面的 containsKey() 和 get() 方法之间从列表中删除该项目。注释部分显示了一种处理此问题的方法,而不会出现 NullPointerException,因为它只是测试 get() 的结果是否为 null。

我的问题是,在 Java 中使用线程安全集合处理这个问题的正确方法是什么?当然,我可以使用互斥体或同步块(synchronized block),但是这是否会破坏线程安全集合的许多优点和易用性?如果我必须使用互斥体或同步块(synchronized block),我不能只使用非线程安全集合来代替吗?此外,我一直听说(在学术界)检查代码是否为空值是不好的编程习惯。我只是疯了吗?这个问题有简单的答案吗?预先感谢您。

package test;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class Test {
    public static void main(String[] args) {
        final Map<Integer, Integer> test = new ConcurrentHashMap<>();

        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                while(true) {
                    test.put(0, 0);
                    Thread.yield();
                }
            }           
        });

        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                while(true) {
                    test.remove(0);
                    Thread.yield();
                }
            }           
        });

        t1.start();
        t2.start();

        while(true) {
            if (test.containsKey(0)) {
                Integer value = test.get(0);
                System.out.println(value);
            }
            Thread.yield();
        }   

        // OR
//      while(true) {
//          Integer value = test.get(0);
//          if (value != null) {
//              System.out.println(value);
//          }
//          Thread.yield();
//      }           
    }
}

最佳答案

what's the right way to handle this problem in Java using thread safe collections?

只执行一个操作,因此它是原子的。它也更快。

    Integer value = test.get(0);
    if (value != null) {               
         System.out.println(value);
    }

I've always heard (in academia) that checking code for null value is bad programming practice. Am I just crazy?

有可能。我认为检查 null(如果值可以为 null)是最佳实践。

关于java - 在 Java 中使用线程安全集合时,处理并发问题的最佳方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19120594/

相关文章:

java - 未在 Spring Controller 中执行验证

c# - 将 Keith Hill 的 PowerShell Get-Clipboard 和 Set-Clipboard 转换为 PSM1 脚本

multithreading - 具有OpenCL的GPU线程同步多核CPU线程

java - 原子变量是否保证 - "happens before relationship"?

java - 将包含 3 列的 CSV 文件读入 Datastream。 JAVA Apache Flink

java - 所有字符都相同的最大字符串的计数和起始索引

java - Android Studio 中的 Google Maps v2。未找到 GeoPoint

Java 线程无法与链表正常工作

sql - PostgreSQL 并发事务问题

java - 线程不通信