|
在JAXP中透明的缓存XSL转换器(5) write(file.getAbsolutePath(), templatesCacheEntry); } else { logger.debug("Using cached transformation [" + file.getAbsolutePath() + "]."); } return templatesCacheEntry.templates.newTransformer(); } 无论如何,我们仍然必须要考虑另外一个问题:线程安全。缓存始终被很多并发进程所共享,我们必须有一个可靠的方法来使读(从缓存中获得所需内容)和写(保存一个新载入的样式表到缓存)操作安全。 虽然Java提供了先进的同步功能,但这里的问题并不是同步,而是如何平衡同步和性能。最简单的方法是全部同步(full synchronization):我们将整个newTransformer(…)方法声明为synchronized,但这种方法效率十分低下。通常我们只有有限的几个样式表,并且并不经常被修改,缓存读的次数要比写的次数要多的多。全部同步(full synchronization)会阻挡其他并发的读取者。首先,这并不是任何时候都需要。第二,这会导致瓶颈问题。 另一方面,使用未同步的容器(比如HashMap)来存储缓存内容非常危险。如果我们没有采取任何措施,那么同时发生的读取和写操作(必然会出现的问题)会导致系统不稳定。 我们主要会遇到一个典型的读/写问题:一个给定的资源,可能有一个写操作和若干个读操作在某一时间同时发生。这个典型的问题也有一个典型的解决方法,来自于Doug Lea的Concurrent Programming in Java。这个方法是,跟踪执行状态(根据计算活动中和等待中的读/写线程的数量确定),只允许在没有任何活动中的写操作线程时才允许读操作。同样,只有在没有活动中的读操作线程时才允许写操作。 为实现以上内容,我们将访问缓存的内容写在两个方法中,read()和write(): 两对berfore/after,read/write方法执行需要线程同步的步骤,确保安全,同时保证了访问缓存的效率。 protected synchronized void beforeRead()
|