Android线程间对象可见性问题:RestResource的Msg变量更新无法读取的解决方法
解决Android中线程间对象变量可见性问题
嘿,我来帮你搞定这个线程可见性的问题!你遇到的情况是t2启动t1后等待其完成,但却看不到Msg变量的更新,结合你给出的代码,咱们一步步来解决:
首先,先修正代码里的核心遗漏
你的GetResource()方法里只获取了remoteResourceList,但没有给Msg变量赋值啊!这大概率是t2看不到更新的首要原因😂。先把这一步补上,比如把远程资源转换成字符串赋值给Msg:
public class RestResource { public volatile String Msg; // volatile保证变量的跨线程可见性 public void GetResource() { List<Resource> remoteResourceList = GetRemoteResource(); // 获取远程资源列表 // 根据实际需求处理资源并赋值给Msg,这里举个简单示例 Msg = "获取到" + remoteResourceList.size() + "条资源"; } // 假设这是你的远程资源获取实现 private List<Resource> GetRemoteResource() { // 实际的网络请求/资源获取逻辑 return new ArrayList<>(); } }
然后,正确实现t2等待t1完成的逻辑
你提到t2要启动t1并等待其完成,这里一定要用Thread.join()方法来确保t1执行完毕后,t2再去读取Msg。如果只是启动t1后直接读取,很可能t1还没来得及更新Msg,t2就已经拿到了旧值。
完整的线程调用示例:
public class ThreadTest { public static void main(String[] args) { RestResource restResource = new RestResource(); // 线程t1:负责调用方法更新Msg Thread t1 = new Thread(() -> { restResource.GetResource(); }); // 线程t2:启动t1并等待其完成,再读取Msg Thread t2 = new Thread(() -> { t1.start(); try { t1.join(); // 阻塞等待t1执行完毕 } catch (InterruptedException e) { e.printStackTrace(); Thread.currentThread().interrupt(); // 重置线程中断状态 } // 此时读取Msg,就能拿到t1更新后的最新值 System.out.println("t2读取到的Msg:" + restResource.Msg); }); t2.start(); } }
为什么这样能解决问题?
volatile关键字:确保Msg变量的更新会立即同步到主内存,其他线程读取时会直接从主内存获取最新值,而不是使用线程本地缓存的旧数据,从根源上解决可见性问题。Thread.join():不仅会让t2阻塞等待t1完成,JMM(Java内存模型)还规定,当t1执行完毕后,其所有内存修改都会对t2可见,相当于隐含了一道内存屏障,进一步保证了数据的一致性。
额外优化建议
- 尽量把
Msg设为私有变量,提供getMsg()方法访问,提升代码封装性:private volatile String msg; public String getMsg() { return msg; } - 如果
GetResource()里有复杂的多步操作,也可以考虑用synchronized方法或者Lock来保证原子性,但你的场景用volatile+join已经完全足够。
内容的提问来源于stack exchange,提问作者Mak Ahmed
相关产品推荐
相关产品推荐

