Java延迟返回值



我有一种情况,我从yaml文件中读取数据对应用程序很重要的数据,因为它在多个类中使用。这是我的代码:

public class CredentialsReader {
    private UserCredentials credentials;
    private boolean isReading = false;

    public CredentialsReader() {
    }
    public void readCredentials() {
        Runnable readerTask = new Runnable() {
            @Override
            public void run() {
                isReading = true;
                parseCredentials();
                isReading = false;
                System.err.println("Parsed credentials");
            }
        };
        ScheduledExecutorService service = Executors.newScheduledThreadPool(1);
        service.scheduleAtFixedRate(readerTask, 0, 60, TimeUnit.SECONDS);
    }
    private void parseCredentials() {
        final File f = new File("/home/dev/IdeaProjects/server/src/main/resources/credentials.yaml");
        try {
            UserCredentials userCredentials = new ObjectMapper().readValue(f, UserCredentials.class);
            this.credentials = userCredentials;
            System.out.println(this.credentials.getUsername() + ", " + this.credentials.getPassword());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }  
    public UserCredentials getCredentials() { return this.credentials; }

}

如您所见,我每分钟阅读数据,我的问题是:
我可以延迟getCredentials的返回值,因此当调用该方法时,我检查isReading是否为true,然后延迟返回,以便我可以保证呼叫者始终获得YAML文件的实际状态?

我认为对于类似情况有适当的锁,但这似乎同步就足够了。

synchronized private void parseCredentials() {...}
synchronized public UserCredentials getCredentials() { ... }

通过声明这些方法一次仅同步一个线程,将能够输入该方法,本质上是一个障碍。这意味着,副标题可能必须等待getCredentials,但是GetCredentials非常快,您永远不会注意到。

将同步在凭证上的实例上,因此,如果您使用多个,则可能需要同步其他内容。如前所述,评论最好在私人对象而不是实例本身上同步。这是一个很小的变化:

public class CredentialsReader {
    private UserCredentials credentials;
    private boolean isReading = false;
    final private Object lock = new Object();
    ...

然后从方法签名中删除同步并在体内添加同步调用。

private void parseCredentials() {
     synchronize(lock){
         //original code goes here.
     }
}

另外,isReading应该是挥发的。

我不建议手动执行此操作,您可以使用jdk中提供的init value 1CountDownLatch

您可以让读者打电话给await,并在准备数据后打电话给countDown

,读者总是可以获取完全初始化的数据。

最新更新