java并发下遇到的地址不同步问题,已解决

先贴上代码:

import java.util.ArrayList;

public class main {
    public static void main(String[] args) {
        HandlerTest handlerTest = new HandlerTest();
        ArrayList<Integer> arrayList = new ArrayList<>();
        for (int i = 0; i < 100; i++) {
            arrayList.add(i);
        }
        handlerTest.setList(arrayList);
        ThreadTest threadTest = new ThreadTest(handlerTest);
        threadTest.start();
        new Thread(()->{
            ArrayList<Integer> list1;
            while (true){
                list1 = handlerTest.getList();
                try {
                    System.out.println("还没死循环。。。。。" + "本地的list" + list1.hashCode() + " 传递的list " + handlerTest.getList().hashCode());
                }catch (Exception e){

                }
                while (list1.size() == 0){
                    System.out.println("本地的list  "+list1.hashCode()+ " 传递的list " + handlerTest.getList().hashCode());

                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
    }
}

import java.util.ArrayList;

public class HandlerTest {
    private volatile ArrayList<Integer> list = new ArrayList<>();

    public ArrayList<Integer> getList() {
        return list;
    }

    public void setList(ArrayList<Integer> list) {
        this.list = list;
    }
}

import java.lang.reflect.Array;
import java.util.ArrayList;

public class ThreadTest extends Thread{
    private HandlerTest ht;
    public ThreadTest(HandlerTest ht){
        this.ht = ht;
    }

    @Override
    public void run() {
        int i = 0;
        while (true){
            this.ht.getList().add(i);
            System.out.println(i);
            i++;
            if (i % 20 == 0) {
                System.out.println("     "+i);
                this.ht.getList().clear();
                this.ht.setList(new ArrayList<>());
                this.ht.getList().clear();
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

遇到的问题就是当ThreadTest 中的代码运行到了i==20的时候就会导致main函数哪里出现死循环导致,后续无法继续运行。
这段代码是我的热运行项目中的一段衍生代码,用来检测有无新的代码。
出现了问题后就将其摘出来debug,最后发现了问题的所在。

先说结果:

结果是这样子的
list1-》list-》实际的内存,然后如果实际的内存中没有数据的话恰巧list1检测到size为空,那么就会进入死循环。那么后续的list1就不会得到更新。所以造成了死循环,究其原因是因为在循环中list1没有及时地得到更新导致的。

原因

也就是结果里提到的但是这个还需要验证一下,具体的验证,博主使用的是hashcode来实现的:

  • 还没死循环。。。。。本地的list377310269 传递的list 377310269
    还没死循环。。。。。本地的list377310269 传递的list 377310269
    还没死循环。。。。。本地的list377310269 传递的list 377310269
    还没死循环。。。。。本地的list377310269 传递的list 377310269
    还没死循环。。。。。本地的list377310269 传递的list 377310269
    还没死循环。。。。。本地的list377310269 传递的list 377310269
    还没死循环。。。。。本地的list377310269 传递的list 377310269
    20
    还没死循环。。。。。本地的list377310269 传递的list 377310269
    本地的list 1 传递的list 1
    本地的list 1 传递的list 1
    本地的list 1 传递的list 1
    20
    本地的list 1 传递的list 51
    21
    本地的list 1 传递的list 49684
    22
    本地的list 1 传递的list 49684
    23
    本地的list 1 传递的list 1540227


    可以看到在i达到了20是的时候出现了死循环,在这之前list1的hashcode和list的hashcode是一样的,之后的就不一样了。

由此可以验证,list1指向的是真实的地址,list指向的也是真实的地址。但是每一次list1的地址的更新都是依靠list的赋值来实现地址的更新所以问题就是在这里出现的,一旦list1不能够被list正常的更新,那么就会出现问题。

而在系循环中list1·是得不到更新的。

解决办法

  1. 在循环中执行更新语句,如:
while (list1.size() == 0){
    System.out.println("本地的list  "+list1.hashCode()+ " 传递的list " + handlerTest.getList().hashCode());

    try {
        Thread.sleep(100);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    /添加的代码
    list1 = handlerTest.getList();
}

2.不使用局部变量,如:

while (handlerTest.getList().size() == 0){
   System.out.println("本地的list  "+list1.hashCode()+ " 传递的list " + handlerTest.getList().hashCode());

   try {
       Thread.sleep(100);
   } catch (InterruptedException e) {
       e.printStackTrace();
   }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值