HashMap&线程
1、HashMap概念
HashMap是一个散列表,存储内容是键值对(key-value)的映射,
HashMap继承了AbstractMap,实现了Map、Cloneable、java.io.Serializable的接口
HashMap的实现不是同步的,线程是不安全的,他的Key 、value都可以为null,此外HashMap中的映射不是有序的。
HashMap实例有两个参数影响其性能,分别是 初始容量、加载因子。加载因子就是哈希表在其容量自动创建之前可以达到多满的一种尺度,注意,当哈希表中的条目容量超出当前加载因子和容量的乘积之后,哈希表进行rehash操作,(重建内部的数据结构)
HashMap的构造函数:
// 默认构造函数。
HashMap()
// 指定“容量大小”的构造函数
HashMap(int capacity)
// 指定“容量大小”和“加载因子”的构造函数
HashMap(int capacity, float loadFactor)
// 包含“子Map”的构造函数
HashMap(Map<? extends K, ? extends V> map)
HashMap是通过“拉链法”实现的哈希表,包括几个重要的成员变量,table、size、threshold、loadfactor、modCount、
table是一个Entry[]数组类型,而 entry就是一个单向链表。键值对就存储在Entry数组中。
threshold是HashMap的阈值,用于判断是否需要调整HashMap的容量。
HashMap主要对外接口,clear() 清空整个HashMap 他是将所有的元素设置成NULL实现的。
1 public void clear() {
2 modCount++;
3 Entry[] tab = table;
4 for (int i = 0; i < tab.length; i++)
5 tab[i] = null;
6 size = 0;
7 }
HashMap中的方法containsKey()判断是否含有Key,containsKey()首先通过getEntry()获取key对应的Entry,然后判断Entry是否是NULL
HashMap中的方法containsValue()判断HashMap是否含有值为value 的元素。
HashMap中的方法entrySet()方法的作用是返回一个HashMap中所用的Entry的集合,他是一个集合
HashMap中的方法get()方法获取key对应的value
HashMap中的发方法put()方法作用是提供对外的接口,让HashMap对象可以通过put()将键值对添加到HashMap中
源代码:
public V put(K key, V value) {
2 // 若“key为null”,则将该键值对添加到table[0]中。
3 if (key == null)
4 return putForNullKey(value);
5 // 若“key不为null”,则计算该key的哈希值,然后将其添加到该哈希值对应的链表中。
6 int hash = hash(key.hashCode());
7 int i = indexFor(hash, table.length);
8 for (Entry<K,V> e = table[i]; e != null; e = e.next) {
9 Object k;
10 // 若“该key”对应的键值对已经存在,则用新的value取代旧的value。然后退出!
11 if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
12 V oldValue = e.value;
13 e.value = value;
14 e.recordAccess(this);
15 return oldValue;
16 }
17 }
18
19 // 若“该key”对应的键值对不存在,则将“key-value”添加到table中
20 modCount++;
21 addEntry(hash, key, value, i);
22 return null;
23 }
HashMap的遍历方式,根据entrySet()获取HashMap的键值对的Set集合,再通过Iterator迭代器遍历得到的集合,
// 假设map是HashMap对象 // map中的key是String类型,value是Integer类型
Integer integ = null; Iterator iter = map.entrySet().iterator();
while(iter.hasNext()) { Map.Entry entry = (Map.Entry)iter.next(); // 获取key key = (String)entry.getKey(); // 获取value integ = (Integer)entry.getValue(); }
2、线程问题
(〃'▽'〃)------object类中的wait()方法导致当前的线程等待,直到其他线程调用notify()方法或者notifyAll()唤醒。
Thread.yield()方法----->线程让步,暂停当前正在执行的线程对象,把机会让给相同或者跟高优先级的线程。
join()----->线程加入,等待其他线程终止,在当前线程中调用另一个贤臣的join() 方法,则当前线程转入阻塞状态,直到另一个线程运行结束,当前线程再由阻塞状态转为就绪状态。
sleep和yield的区别:
sleep方法是当前线程进入停止状态,所以执行sleep()的线程在指定的时间内不会被执行,yield()只是使得当前线程重新回到可执行状态,所以调用yield()方法的线程可能会进入到执行状态后马上又被执行。 (〃'▽'〃)---- wait()和notify()方法含义:obj.wait()与obj.ootify()必须要与synchronize一起使用,wait和notify是针对已近获取了obj锁进行的操作,从语法角度上说就是Obj.wait(),Obj.notify必须在synchronized(Obj){...}语句块内
,从功能上说wait就是说线程获取对象锁之后,主动释放对象锁,同时 本线程休眠,直到其他的线程调用对象的notify方法唤醒线程,才能继续获得对象锁,并继续执行。notify()调用后并不是马上释放对象锁,二是在响应的synchronize{}语句块执行完之后,自动释放锁。主要就是wait()方法释放CPU的同时,释放了对象锁的控制。
如下:是一个使用锁机制结合HashMap
public class CallThread2 {
static int index = 0;
static int max = 4 * 2;
static HashMap<Integer, List<Integer>> map = new HashMap<Integer, List<Integer>>();
static {
for (int i = 0; i < 4; i++) {
map.put(i, new ArrayList<Integer>());
}
}
static boolean isRunning = true; //声明一个标志初始化为真
public static class MyRunnable implements Runnable {
int name;
Lock lock;
Condition condition;
private MyRunnable(int name, Lock lock, Condition condition) {
super();
this.name = name;
this.lock = lock;
this.condition = condition;
}
public boolean isMyName(int index) {
while (index != name) {
myWait();
if(!isRunning)return false;
return true;
}
return false;
}
public void myWait() {
lock.lock(); //获得锁
try {
condition.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
lock.unlock();
}
public void myNotifyAll() {
lock.lock();
condition.signalAll();
lock.unlock();
}
@Override
public void run() {
// TODO Auto-generated method stub
while (isRunning) {
while (isMyName(index % 4)) {
}
if(!isRunning)return;
for (int i = 0, arrIndex = index; i < 4; i++) {
try {
if (arrIndex-- < 0) {
break;
}
List<Integer> list = map.get(i);
if (list.size() < max) {
list.add(name + 1);
}
} catch (Exception e) {
}
}
System.err.println("A:" + map.get(0));
System.err.println("B:" + map.get(1));
System.err.println("C:" + map.get(2));
System.err.println("D:" + map.get(3));
System.err.println("-----------------------");
if (map.get(map.size() - 1).size() == max) {
isRunning = false;
myNotifyAll();
return;
} else {
index++;
}
myNotifyAll();
}
HashMap&线程的更多相关文章
- HashMap的实现原理?如何保证HashMap线程安全?
A:HashMap简单说就是它根据建的hashcode值存储数据的,大多数情况下可以直接定位到它的值,因而具有很快的访问速度,但遍历的顺序是不确定的. B:HashMap基于哈希表,底层结构由数组来实 ...
- (转载)两种方法让HashMap线程安全
HashMap不是线程安全的,往往在写程序时需要通过一些方法来回避.其实JDK原生的提供了2种方法让HashMap支持线程安全. 方法一:通过Collections.synchronizedMap() ...
- HashMap线程不安全的体现
前言:我们都知道HashMap是线程不安全的,在多线程环境中不建议使用,但是其线程不安全主要体现在什么地方呢,本文将对该问题进行解密. 1.jdk1.7中的HashMap 在jdk1.8中对HashM ...
- 谈谈HashMap线程不安全的体现
原文出处: Hosee HashMap的原理以及如何实现,之前在JDK7与JDK8中HashMap的实现中已经说明了. 那么,为什么说HashMap是线程不安全的呢?它在多线程环境下,会发生什么情况呢 ...
- 为什么HashMap线程不安全,Hashtable和ConcurrentHashMap线程安全
HashMap源码 public V put(K key, V value) { return putVal(hash(key), key, value, false, true); } final ...
- 如何保证HashMap线程安全
可使用Java 1.5推荐的java.util.concurrent包ConcurrentHashMap来实现,内部不再使用类似HashTable的synchronized同步锁,而是使用Reentr ...
- hashmap,hashTable concurrentHashMap 是否为线程安全,区别,如何实现的
线程安全类 在集合框架中,有些类是线程安全的,这些都是jdk1.1中的出现的.在jdk1.2之后,就出现许许多多非线程安全的类. 下面是这些线程安全的同步的类: vector:就比arraylist多 ...
- 为什么HashMap不是线程安全的
电面突然被问到这个问题,之前看到过,但是印象不深,导致自己没有答出来,现在总结一下. HashMap的内部存储结构 transient Node<K,V>[] table; static ...
- 如何线程安全的使用HashMap
本文转自:http://www.importnew.com/21396.html 面试时被问到HashMap是否是线程安全的,如何在线程安全的前提下使用HashMap,其实也就是HashMap,Has ...
随机推荐
- day 3 - 2 数据类型练习
1.有变量 name = " aleX leNB " 完成如下操作 name = " aleX leNB " # 1) 移除两端空格n1 = name.stri ...
- python 06
1.集合 增: s.add(8) print(s) s.update('alex') # 迭代添加 print(s) 删 s = {1,2,3,'22','ss',(3,4)} s1 = s.pop( ...
- linux 软件包管理介绍
- linux 终端命令行的快捷键列表
终端有很多快捷键,不太好记,常用的在这里 Ctrl+r 实现快速检索使用过的历史命令.Ctrl+r中r是retrieve中r.Ctrl+a:光标回到命令行首. (a:ahead)Ctrl+e:光标回到 ...
- 在Apache Struts中利用OGNL注入
前言 本文简要介绍了Apache Struts的OGNL注入缺陷,文章中介绍使用简单的应用程序复现OGNL注入.深入研究针对公共漏洞,并理解这类漏洞. 内容 安装Apache Tomcat服务器(入门 ...
- 【转】Python之mmap内存映射模块(大文本处理)说明
[转]Python之mmap内存映射模块(大文本处理)说明 背景: 通常在UNIX下面处理文本文件的方法是sed.awk等shell命令,对于处理大文件受CPU,IO等因素影响,对服务器也有一定的压力 ...
- Saltstack自动化操作记录(1)-环境部署
早期运维工作中用过稍微复杂的Puppet,下面介绍下更为简单实用的Saltstack自动化运维的使用. Saltstack知多少Saltstack是一种全新的基础设施管理方式,是一个服务器基础架构集中 ...
- java官网真不错
要用到一个软件,打开时说没找到javaw,然后大家说这是因为没安装java,就按着链接去了java官网 https://www.java.com/zh_CN/download/faq/remove_o ...
- requests库入门03-get请求
先看一个没有请求参数的get请求,访问百度首页 import requests r = requests.get('https://www.baidu.com') print(r.status_cod ...
- nodejs+express+mongodb简单的例子
简单的介绍下node+express+mongodb这三个东西.node:是运行在服务器端的程序语言,表面上看过去就是javascript一样的东西,但是呢,确实就是服务器语言,个人觉得在一定层次上比 ...