- Java code
package thread;import java.util.Map;import java.util.concurrent.ConcurrentHashMap;public class ConcurrentHashMapTest{ Map<String, String> map = new ConcurrentHashMap<String, String>(); /** * 添加 */ public void initMap() { for (int i = 0; i < 10000; i++) { map.put("" + i, "" + i); } } /** * 查询 */ public Map<String, String> getMap() { try { Thread.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } return map; } public String getValue(String key) { try { Thread.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } return map.get(key); } public static void main(String[] args) { ConcurrentHashMapTest mapTest = new ConcurrentHashMapTest(); // 初始化 new TestThread(mapTest).start(); // 查询 // System.out.println(mapTest.getValue("9999")); // 查询 System.out.println(mapTest.getMap().size()); }}/** * 测试线程类 */class TestThread extends Thread{ ConcurrentHashMapTest mapTest = null; public TestThread(ConcurrentHashMapTest _mapTest) { this.mapTest = _mapTest; } /** * */ @Override public void run() { mapTest.initMap(); }}class TestThread2 extends Thread{ ConcurrentHashMapTest mapTest = null; public TestThread2(ConcurrentHashMapTest _mapTest) { this.mapTest = _mapTest; } /** * */ @Override public void run() { mapTest.getMap(); }}
代码如上:这里有一个问题一直纠结我很久了,想问下.
这里用的线程安全的集合ConcurrentHashMap,按理说它提供的所有方法都是线程安全的,在操作ConcurrentHashMap不需要做其它线程安全的处理了。
但是在测试过程中发现假如有两个线程同时操作map,一个执行initMap操作,一个执行getMap,这个时候预期System.out.println(mapTest.getMap().size());这段代码会返回10000,但是执行的结果发现这个返回值会每次都不一样。
这样的话是不是需要在两个方法中将map加上同步代码块?我测试过加上同步代码块后
- Java code
/** * 添加 */ public void initMap() { synchronized (map) { for (int i = 0; i < 10000; i++) { map.put("" + i, "" + i); } } } /** * 查询 */ public Map<String, String> getMap() { try { // 让其它线程先持有map的锁 Thread.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (map) { return map; } }
System.out.println(mapTest.getMap().size());这段代码会始终返回10000.
综上所述:在多线程的环境中使用了线程安全的集合类型,是否还需要在方法中对集合进行同步?
P.S:附上jdk中对于线程安全集合(CopyOnWriteArraySet)的一个示例用法,请大鸟释疑,谢谢!
示例用法。 以下代码使用一个写时复制(copy-on-write)的 set,以维护在状态更新时执行某项操作的一组 Handler 对象。
- Java code
class Handler { void handle(); ... }class X { private final CopyOnWriteArraySet<Handler> handlers = new CopyOnWriteArraySet<Handler>(); public void addHandler(Handler h) { handlers.add(h); } private long internalState; private synchronized void changeState() { internalState = ...; } public void update() { changeState(); for (Handler handler : handlers) handler.handle(); } }
------解决方案--------------------