您的位置:首页 > 编程语言 > Java开发

【深入Java基础】HashMap的高级用法(二):同步

2018-01-30 18:07 405 查看

HashMap的高级用法:同步

HashMap是不支持同步的,不能用于多线程中。而HashTable是同步的,这个日后再论。我们可以使用以下两种方法来实现HashMap的同步:

使用
ConcurrentHashMap


使用
Collections.synchronizedMap
获取同步map

使用ConcurrentHashMap

ConcurrentHashMap<Integer,String> concurrentHashMap = new ConcurrentHashMap<>();


使用Collections.synchronizedMap获取同步map

HashMap<Integer,String> hashMap = new HashMap<>();
Map<Integer,String> synchronizedMap = Collections.synchronizedMap(hashMap);


测试

对于没有同步的HashMap在多线程中运行一定会抛出异常:

java.util.ConcurrentModificationException


运行两个线程同时对一个hashmap进行读写操作:

HashMap<Integer,String> hashMap1 = new HashMap<>();
//写线程
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
hashMap1.put(i,"value"+i);
try {
Thread.sleep(new Random().nextInt(10));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
//读线程
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
if (hashMap1.size() > 0) {
for (Map.Entry entry : hashMap1.entrySet()) {
System.out.println(entry.getKey() + "=" + entry.getValue());
}
}
try {
Thread.sleep(new Random().nextInt(10));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();


运行以上代码抛出异常
java.util.ConcurrentModificationException
。原因是未实现同步时,在迭代hashmap的时候不能修改数据。

Collections.synchronizedMap实现同步:

HashMap<Integer,String> hashMap1 = new HashMap<>();
Map<Integer, String> map = Collections.synchronizedMap(hashMap1);
//写线程
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
map.put(i,"value"+i);
try {
Thread.sleep(new Random().nextInt(10));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
//读线程
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
if (map.size() > 0) {
for (Map.Entry entry : map.entrySet()) {
System.out.println(entry.getKey() + "=" + entry.getValue());
}
}
try {
Thread.sleep(new Random().nextInt(10));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();


运行以上代码任然抛出异常
java.util.ConcurrentModificationException
。可见该方法并不安全。(还是这样测试有问题?)

ConcurrentHashMap实现同步:

  ConcurrentHashMap<Integer,String> concurrentHashMap = new ConcurrentHashMap<>();
//写线程
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
concurrentHashMap.put(i,"value"+i);
try {
Thread.sleep(new Random().nextInt(10));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
//读线程
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
if (concurrentHashMap.size() > 0) {

ca59
for (Map.Entry entry : concurrentHashMap.entrySet()) {
System.out.println(entry.getKey() + "=" + entry.getValue());
}
}
try {
Thread.sleep(new Random().nextInt(10));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();


运行以上代码,无异常。

所以为了保证多线程下的hashmap的数据一致性使用ConcurrentHashMap最为合理。并且ConcurrentHashMap的效率也比较高。为什么日后再论。

使用lock锁手动实现hashmap的同步:

ReentrantLock lock = new ReentrantLock(true);
HashMap<Integer, String> hashMap1 = new HashMap<>();

//写线程
new Thread(new Runnable() {
@Override
public void run() {
try {
for (int i = 0; i < 1000; i++) {
hashMap1.put(i, "value" + i);
try {
Thread.sleep(new Random().nextInt(10));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} catch (Exception e) {

} finally {
//lock.unlock();
}
}
}).start();

//读线程
new Thread(new Runnable() {
@Override
public void run() {

while (true) {
lock.lock();
try {
if (hashMap1.size() > 0) {
for (Map.Entry entry : hashMap1.entrySet()) {
System.out.println(entry.getKey() + "=" + entry.getValue());
}
}
} catch (Exception e) {
System.out.println(e.getMessage());
} finally {
lock.unlock();
}

try {
Thread.sleep(new Random().nextInt(10));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息