天天看点

性能优化总结(四):预加载的设计

什么是预加载,为什么要用它?

我们所需要的api

一个简单的例子

什么是预加载?

    预加载其实就是在真正开始使用数据之前,先异步把数据加载好,等到需要使用时,就可以直接使用之前加载好的数据。这时,由于数据已经加载完成,而不用等待漫长的加载过程,所以程序的速度得到一个明显的提升。

    那么,什么时候需要使用它呢?我觉得,主要是这种情况:当我们可以预知程序接下来的步骤中,很可能会用到一些数据,而获取这些数据的操作比较耗时的时候,我们就可以使用预加载的方式,提前把数据准备好。

    预加载需要使用异步方法,也就是使用后台线程来加载数据。这样做的好处当然是不会阻塞当前的主线程。(不过如果当前线程本身就是用于异步加载数据的话,那就没必要再新开线程了。)

    但是,这些并不是我想要的api……

    目前系统中预加载使用的场景需求是这样的:

预加载可以对指定的数据获取操作(loading action)进行封装,在需要时调用。

使用数据的模块(使用者),并不一定知道是谁、在何时给它提前加载的数据。它只会申请使用数据。

发起异步加载的模块(发起者),应该知道使用者是谁。

多个发起者之间没有关系,但是都可以为某一使用者发起预加载。但是保证真正的数据加载操作,只会发生一次。

支持重新加载。

一个类中,支持对它不同的数据进行不同加载方式,以方便按需加载。

从使用者的角度来看,不管有没有发起者为它进行预加载,它都可以申请并拿到想要的数据。也就是说:

当没有发起者为它进行预加载,那么它的数据申请会导致即时的数据加载;

如果已经发起了预加载,而且数据已经加载完成,则直接获取到加载好的数据;

如果数据没有完成,则数据使用者需要等待数据的加载完成后,才可以获取到数据并继续当前的操作。

    其中,最重要的就是最后点。

    可以看到,这里需要用到异步操作、线程间同步。所以我们需要基于上面提到的多种api来实现,这里我们使用的是简单的线程池的方式,比较简单,不再赘述。

    最后设计出的api大致是这样的: