可以多运行几次这个代码就会遇到死循环,请高手分析分析是什么原因导致死循环。import java.util.HashMap;public class TestHashMap {
private HashMap map = new HashMap();
private void putData(){
for(int i=0;i<100000;i++){
map.put(new Key(i), new Integer(i));
//map.put("1", "1");
if(i%100 ==0){
System.out.println("put i="+i+" thread="+Thread.currentThread().getName());
//System.out.println("size=" + map.toString());
}
reset();
}
System.out.println("put end thread="+Thread.currentThread().getName());
}// end putData
/**这个方法如果加上同步 private synchronized void reset(),仍然可能出现死循环,只是概率小一些,请不要关注这里
* 重新指定hashmap。
*/
private synchronized void reset(){
if(map.size() > 1000){
map.clear();
map = new HashMap();
}
}//end reset
private class Key{
int v ;
private Key(int v){
this.v = v;
}
public int hashCode() {//返回相同的hash值
return 1;
}
public boolean equals(Object obj) {//由v值确定
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Key other = (Key) obj;
if (!getOuterType().equals(other.getOuterType()))
return false;
if (v != other.v)
return false;
return true;
}
private TestCircleHashMap getOuterType() {
return TestCircleHashMap.this;
}
}//end class
public static void main(String[] args) {
final TestHashMap test = new TestHashMap ();
for(int i=0;i<2;i++){
new Thread("Thread_"+i){
public void run(){
test.putData();
}
}.start();
}
}
}
private HashMap map = new HashMap();
private void putData(){
for(int i=0;i<100000;i++){
map.put(new Key(i), new Integer(i));
//map.put("1", "1");
if(i%100 ==0){
System.out.println("put i="+i+" thread="+Thread.currentThread().getName());
//System.out.println("size=" + map.toString());
}
reset();
}
System.out.println("put end thread="+Thread.currentThread().getName());
}// end putData
/**这个方法如果加上同步 private synchronized void reset(),仍然可能出现死循环,只是概率小一些,请不要关注这里
* 重新指定hashmap。
*/
private synchronized void reset(){
if(map.size() > 1000){
map.clear();
map = new HashMap();
}
}//end reset
private class Key{
int v ;
private Key(int v){
this.v = v;
}
public int hashCode() {//返回相同的hash值
return 1;
}
public boolean equals(Object obj) {//由v值确定
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Key other = (Key) obj;
if (!getOuterType().equals(other.getOuterType()))
return false;
if (v != other.v)
return false;
return true;
}
private TestCircleHashMap getOuterType() {
return TestCircleHashMap.this;
}
}//end class
public static void main(String[] args) {
final TestHashMap test = new TestHashMap ();
for(int i=0;i<2;i++){
new Thread("Thread_"+i){
public void run(){
test.putData();
}
}.start();
}
}
}
和
map = Collections.synchronizedMap(new HashMap());
因为HashMap不是线程安全的,所以会导致不正确
private HashMap map = new HashMap();
private void putData(){
for(int i=0;i <100000;i++){
map.put(new Key(i), new Integer(i));
//map.put("1", "1");
if(i%100 ==0){
System.out.println("put i="+i+" thread="+Thread.currentThread().getName());
//System.out.println("size=" + map.toString());
}
reset();
}
System.out.println("put end thread="+Thread.currentThread().getName());
}// end putData
/**这个方法如果加上同步 private synchronized void reset(),仍然可能出现死循环,只是概率小一些,请不要关注这里
* 重新指定hashmap。
*/
private synchronized void reset(){
if(map.size() > 1000){
map.clear();
map = new HashMap();
}
}//end reset
private class Key{
int v ;
private Key(int v){
this.v = v;
}
public int hashCode() {//返回相同的hash值
return 1;
}
public boolean equals(Object obj) {//由v值确定
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Key other = (Key) obj;
if (!getOuterType().equals(other.getOuterType()))
return false;
if (v != other.v)
return false;
return true;
}
private TestHashMap getOuterType() {
return TestHashMap.this;
}
}//end class
public static void main(String[] args) {
final TestHashMap test = new TestHashMap ();
for(int i=0;i <2;i++){
new Thread("Thread_"+i){
public void run(){
test.putData();
}
}.start();
}
}
}
如:资源抢占等,
e1.next = e2;
e2.next = null;线程1修改,放入eNew1,eNew2
所以将试图变成e1.next = e2;
e2.next = eNew1;
eNew1.next = eNew2;
eNew2.next = null;
但是同时线程2也放入内容,但是同时它试图修改放大table的大写以减少同时放在table[i]中的数量
table[i]
e.next = e2;
e2.next = null;table[j]
eNew2.next = eNew1;
eNew1.next = null;
但是两者同时修改,结果导致变成
eNew2.next = eNew1;
eNew1.next = eNew2;这样就是一个死循环了。上面只是一种情况,事实由于并发的不确定性,可能还会出现其它问题
所以你应该同步这个Map
private HashMap map = new HashMap();
private void putData(){
for(int i=0;i <100000;i++){
put(new Key(i), new Integer(i));
//map.put("1", "1");
if(i%100 ==0){
System.out.println("put i="+i+" thread="+Thread.currentThread().getName());
//System.out.println("size=" + map.toString());
}
reset();
}
System.out.println("put end thread="+Thread.currentThread().getName());
}// end putData
/**这个方法如果加上同步 private synchronized void reset(),仍然可能出现死循环,只是概率小一些,请不要关注这里
* 重新指定hashmap。
*/
private void reset(){
if(map.size() > 1000){
map.clear();
map = new HashMap();
}
}//end reset
private synchronized void put(Key k,Integer i){
map.put(k, i);
}