Java 如何在变量在多个类中更改时同步对变量的访问?

Java 如何在变量在多个类中更改时同步对变量的访问?,java,spring,multithreading,Java,Spring,Multithreading,我有一个调度程序类和另一个自定义http客户端类 调度器在应用程序启动时初始化,并在后台执行工作,例如每30秒查询一次服务(url),并将数据写入日志 http客户端也是使用url创建的 url可以随时更改,因此我需要确保无论何时,日志调度程序和http客户端都使用新url重新初始化 public class LogScheduler { public log() { synchronized(globallock) { String url = getUrl();

我有一个调度程序类和另一个自定义http客户端类

调度器在应用程序启动时初始化,并在后台执行工作,例如每30秒查询一次服务(url),并将数据写入日志

http客户端也是使用url创建的

url可以随时更改,因此我需要确保无论何时,日志调度程序和http客户端都使用新url重新初始化

public class LogScheduler {
   public log() {
     synchronized(globallock) {
       String url = getUrl();
       //log some activity
     }
   }
}
我们有另一个调度器,它每30分钟寻找一个新的url

public class UrlScheduler {
   private volatile String url;
   public void check() {
     String url = service.getNewUrl();
     if(url!=this.url) {
       synchronized(globallock) {
        this.url=url;
        reinitialize http client
       }
     }
   }
   public String getUrl(){
    return url;
   }
}
现在,我正在使用全局锁来确保日志调度器在url调度器更改该值时立即看到该值。我真的不喜欢使用全局锁的想法,因为它会破坏封装以及其他问题

我如何更改设置,以便在url更改后立即重新初始化日志计划程序和http客户端,并按顺序更改后同步它们?若url并没有改变,我想避免重新初始化

另外,如果请求发出时url正在更新,如何使用http客户端阻止ui线程

这是一个spring应用程序


如果不清楚,请告诉我,我很乐意提供更多细节。

我相信观察者模式在这里很有用

URL调度程序,或负责知道URL在任何给定点(称为主题)的状态的任何类,将维护一个
观察者列表(当URL更改时希望得到通知的其他对象),即日志调度程序和其他http客户端

观察者只需实现一个接口,该接口提供一个通知函数,该函数接受新URL作为参数。每当url发生更改时,主题通过调用其通知函数通知其观察者列表中的每个人

这使得日志调度器和其他http客户机仅在URL更改时收到通知,并立即收到通知


如果希望解耦观察者和主题(通常在有许多观察者观察许多主题时更有用),可以使用中介模式构建事件管理器。然而,考虑到您的需求,这可能有些过分

在信息有限的情况下工作,如果有任何问题,请告诉我,我会改变它

对我来说,最简单的事情是将HTTPClient与可能需要它的任何东西分离。解耦客户端意味着您不需要在专注于其他事情的类中处理同步问题(例如,记录或ping服务)

这是一张图表

看起来你的变化很小。主要的区别是您要为您的HTTPClient创建一个包装器,这样您就可以在客户端中同步它,以确保HTTPClient始终是正确的

作为一个示例包装器,不要使用它,因为它非常简单

public class HTTPClientProxy{

    private final Object syncLock = new Object();

    private HTTPClient client;

    public HTTPClient getClient(){
        synchronized(syncLock){
            return client;
        }
    }

    public void updateClient(URL url){
        synchronized(syncLock){
            client = new HTTPClient(url);
        }
    }
}

一个潜在的问题,一个我不确定的问题。如果您有多个服务,并且它们都是bundler(例如,被链接并且需要使用相同的URL)。然后,您需要在这一侧设置其他内容,以便确保它们都使用相同的客户端。不过,这将是一个良好的开端,因为它可以让您不再担心从HTTPClient获取坏数据,并将该功能移动到代理类中。

是否必须使用URL初始化对象?或者,他们可以在需要发出请求时动态获取它们吗?我的意思是,不要将其存储为类变量,您可以使用提供程序或任何东西吗?一旦我们知道url发生更改,就必须立即初始化对象。因此,下次任何对资源的请求/访问都将使用新url获取数据。等等,有多少类正在使用此url?这仅仅是日志记录程序,还是你有其他的东西?你不仅仅有一个同步问题,你显然也有一个及时更新的问题。也许你可以澄清一下。@JamesKPolk这是一个很好的例子。有点奇怪,答案是在java中,问题是在C++中,尽管哈哈尔谢谢你。在spring应用程序中如何进行类似的操作?我不知道你的意思。不管是否是Spring应用程序,它都是基于Java构建的,这是一种可以用Java实现的软件模式。只需让需要通知的类实现一个提供通知功能的
observer
接口,并让state类保存这些观察者的列表。也许让观察者在主题中注册自己(将自己添加到观察者列表中)。每当url更改时,循环该列表并调用每个通知函数。