MST
星途 面试题库

面试题:Java Hashtable在多线程高并发写入场景下的问题及解决方案

在多线程高并发写入的场景中,Java Hashtable会出现什么问题?如果要求你对该场景下的Hashtable使用进行优化,你会采取哪些措施,结合代码示例说明。
27.6万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试

1. Hashtable在多线程高并发写入场景的问题

  • 性能问题:Hashtable内部使用synchronized关键字修饰方法,这意味着同一时刻只有一个线程能访问Hashtable的任何方法,在高并发写入场景下,大量线程会被阻塞,导致性能低下。
  • 死锁风险:在复杂的多线程环境中,如果多个线程对Hashtable进行嵌套同步访问,可能会导致死锁。

2. 优化措施及代码示例

使用ConcurrentHashMap替换Hashtable

import java.util.concurrent.ConcurrentHashMap;

public class ConcurrentHashMapExample {
    private static ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();

    public static void main(String[] args) {
        Thread thread1 = new Thread(() -> {
            for (int i = 0; i < 1000; i++) {
                map.put("key" + i, i);
            }
        });

        Thread thread2 = new Thread(() -> {
            for (int i = 1000; i < 2000; i++) {
                map.put("key" + i, i);
            }
        });

        thread1.start();
        thread2.start();

        try {
            thread1.join();
            thread2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("Map size: " + map.size());
    }
}

ConcurrentHashMap采用了更加细粒度的锁机制(例如分段锁或基于CAS操作),允许多个线程同时访问不同的段,大大提高了并发性能。

使用Collections.synchronizedMap并指定合适的锁粒度(如果必须使用类似Hashtable的同步行为)

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

public class SynchronizedMapExample {
    private static Map<String, Integer> synchronizedMap;

    public static void main(String[] args) {
        Map<String, Integer> map = new HashMap<>();
        synchronizedMap = Collections.synchronizedMap(map);

        Thread thread1 = new Thread(() -> {
            for (int i = 0; i < 1000; i++) {
                synchronized (synchronizedMap) {
                    synchronizedMap.put("key" + i, i);
                }
            }
        });

        Thread thread2 = new Thread(() -> {
            for (int i = 1000; i < 2000; i++) {
                synchronized (synchronizedMap) {
                    synchronizedMap.put("key" + i, i);
                }
            }
        });

        thread1.start();
        thread2.start();

        try {
            thread1.join();
            thread2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("Map size: " + synchronizedMap.size());
    }
}

这里通过Collections.synchronizedMap创建一个同步的Map,并且手动控制同步块,缩小锁的粒度,减少线程竞争,从而在一定程度上提高并发性能。但这种方式相较于ConcurrentHashMap,性能还是会低一些,因为整体的同步粒度还是相对较粗。