如何从运行中的程序实例取值并实现跨进程修改运行状态标记
现有代码的核心问题
你当前写的run方法接收的是基本类型boolean参数,Java是值传递逻辑,方法内部拿到的只是这个参数的副本,就算外部修改了原始变量,方法内的runstate也不会同步更新,循环根本停不下来。如果是跨进程场景,两个进程的内存空间完全隔离,也不可能直接修改对方的内部变量,必须借助进程间通信(IPC)机制实现。
场景1:同进程内多线程场景(大部分人初期容易把线程和进程混淆)
如果只是同一个进程内的第二个线程要修改运行标记,你需要把状态标记改为成员变量,并用volatile关键字修饰保证多线程之间的可见性,避免线程将变量缓存到私有工作内存,修改后其他线程无法感知。
修改后的代码示例:
class Sample{ // volatile修饰保证多线程可见性 private volatile boolean runstate = true; public void run() { while(runstate){ // 执行业务逻辑 } } // 对外提供修改状态的方法 public void stopRunning() { this.runstate = false; } }
使用时将同一个Sample实例传给执行业务的线程,第二个线程直接调用实例的stopRunning()方法,就能修改标记让业务线程退出循环。
场景2:跨独立进程场景
两个进程内存完全隔离,无法直接访问对方的内部数据,必须用进程间通信方案实现,常见可选方案如下:
- 本地文件/共享存储:把状态标记存在双方约定好的本地文件中,第一个进程运行时定时读取文件判断状态,第二个进程要停止应用时直接修改文件内容即可,实现成本最低,适合对状态更新延迟要求不高的场景
- 本地Socket通信:第一个进程启动本地Socket服务端监听指定端口,第二个进程作为客户端发送停止指令,第一个进程收到指令后将自身运行标记设为false即可,实时性高
- 共享内存:借助操作系统提供的共享内存机制,两个进程映射同一块内存区域存储状态标记,Java中可以用
MappedByteBuffer实现 - 系统信号:类Unix系统可以给第一个进程发送自定义信号,第一个进程提前注册信号处理器,收到信号后修改运行标记即可
注意:不管用哪种跨进程方案,第一个进程的业务循环都不能完全阻塞所有事件响应逻辑,必须预留定时检查状态或者响应外部事件的逻辑,否则收到停止指令也无法处理。
内容的提问来源于stack exchange,提问作者AyyappaLokesh Garlapati
相关产品推荐
相关产品推荐

