diff options
Diffstat (limited to 'guava/src/com/google/common/cache/CacheBuilder.java')
-rw-r--r-- | guava/src/com/google/common/cache/CacheBuilder.java | 195 |
1 files changed, 75 insertions, 120 deletions
diff --git a/guava/src/com/google/common/cache/CacheBuilder.java b/guava/src/com/google/common/cache/CacheBuilder.java index 105ff73..8eef200 100644 --- a/guava/src/com/google/common/cache/CacheBuilder.java +++ b/guava/src/com/google/common/cache/CacheBuilder.java @@ -26,6 +26,7 @@ import com.google.common.annotations.GwtCompatible; import com.google.common.annotations.GwtIncompatible; import com.google.common.base.Ascii; import com.google.common.base.Equivalence; +import com.google.common.base.Equivalences; import com.google.common.base.Objects; import com.google.common.base.Supplier; import com.google.common.base.Suppliers; @@ -56,12 +57,8 @@ import javax.annotation.CheckReturnValue; * <li>values automatically wrapped in {@linkplain WeakReference weak} or * {@linkplain SoftReference soft} references * <li>notification of evicted (or otherwise removed) entries - * <li>accumulation of cache access statistics * </ul> * - * These features are all optional; caches can be created using all or none of them. By default - * cache instances created by {@code CacheBuilder} will not perform any type of eviction. - * * <p>Usage example: <pre> {@code * * LoadingCache<Key, Graph> graphs = CacheBuilder.newBuilder() @@ -75,19 +72,8 @@ import javax.annotation.CheckReturnValue; * } * });}</pre> * - * Or equivalently, <pre> {@code - * - * // In real life this would come from a command-line flag or config file - * String spec = "maximumSize=10000,expireAfterWrite=10m"; * - * LoadingCache<Key, Graph> graphs = CacheBuilder.from(spec) - * .removalListener(MY_LISTENER) - * .build( - * new CacheLoader<Key, Graph>() { - * public Graph load(Key key) throws AnyException { - * return createExpensiveGraph(key); - * } - * });}</pre> + * These features are all optional. * * <p>The returned cache is implemented as a hash table with similar performance characteristics to * {@link ConcurrentHashMap}. It implements all optional operations of the {@link LoadingCache} and @@ -139,16 +125,13 @@ import javax.annotation.CheckReturnValue; * retain all the configuration properties of the original cache. Note that the serialized form does * <i>not</i> include cache contents, but only configuration. * - * <p>See the Guava User Guide article on <a href= - * "http://code.google.com/p/guava-libraries/wiki/CachesExplained">caching</a> for a higher-level - * explanation. - * * @param <K> the base key type for all caches created by this builder * @param <V> the base value type for all caches created by this builder * @author Charles Fry * @author Kevin Bourrillion * @since 10.0 */ +@Beta @GwtCompatible(emulated = true) public final class CacheBuilder<K, V> { private static final int DEFAULT_INITIAL_CAPACITY = 16; @@ -180,10 +163,10 @@ public final class CacheBuilder<K, V> { }); static final CacheStats EMPTY_STATS = new CacheStats(0, 0, 0, 0, 0, 0); - static final Supplier<StatsCounter> CACHE_STATS_COUNTER = - new Supplier<StatsCounter>() { + static final Supplier<SimpleStatsCounter> CACHE_STATS_COUNTER = + new Supplier<SimpleStatsCounter>() { @Override - public StatsCounter get() { + public SimpleStatsCounter get() { return new SimpleStatsCounter(); } }; @@ -236,7 +219,7 @@ public final class CacheBuilder<K, V> { RemovalListener<? super K, ? super V> removalListener; Ticker ticker; - Supplier<? extends StatsCounter> statsCounterSupplier = NULL_STATS_COUNTER; + Supplier<? extends StatsCounter> statsCounterSupplier = CACHE_STATS_COUNTER; // TODO(fry): make constructor private and update tests to use newBuilder CacheBuilder() {} @@ -250,34 +233,8 @@ public final class CacheBuilder<K, V> { } /** - * Constructs a new {@code CacheBuilder} instance with the settings specified in {@code spec}. - * - * @since 12.0 - */ - @Beta - @GwtIncompatible("To be supported") - public static CacheBuilder<Object, Object> from(CacheBuilderSpec spec) { - return spec.toCacheBuilder() - .lenientParsing(); - } - - /** - * Constructs a new {@code CacheBuilder} instance with the settings specified in {@code spec}. - * This is especially useful for command-line configuration of a {@code CacheBuilder}. - * - * @param spec a String in the format specified by {@link CacheBuilderSpec} - * @since 12.0 - */ - @Beta - @GwtIncompatible("To be supported") - public static CacheBuilder<Object, Object> from(String spec) { - return from(CacheBuilderSpec.parse(spec)); - } - - /** * Enables lenient parsing. Useful for tests and spec parsing. */ - @GwtIncompatible("To be supported") CacheBuilder<K, V> lenientParsing() { strictParsing = false; return this; @@ -286,10 +243,9 @@ public final class CacheBuilder<K, V> { /** * Sets a custom {@code Equivalence} strategy for comparing keys. * - * <p>By default, the cache uses {@link Equivalence#identity} to determine key equality when - * {@link #weakKeys} is specified, and {@link Equivalence#equals()} otherwise. + * <p>By default, the cache uses {@link Equivalences#identity} to determine key equality when + * {@link #weakKeys} is specified, and {@link Equivalences#equals()} otherwise. */ - @GwtIncompatible("To be supported") CacheBuilder<K, V> keyEquivalence(Equivalence<Object> equivalence) { checkState(keyEquivalence == null, "key equivalence was already set to %s", keyEquivalence); keyEquivalence = checkNotNull(equivalence); @@ -303,11 +259,10 @@ public final class CacheBuilder<K, V> { /** * Sets a custom {@code Equivalence} strategy for comparing values. * - * <p>By default, the cache uses {@link Equivalence#identity} to determine value equality when - * {@link #weakValues} or {@link #softValues} is specified, and {@link Equivalence#equals()} + * <p>By default, the cache uses {@link Equivalences#identity} to determine value equality when + * {@link #weakValues} or {@link #softValues} is specified, and {@link Equivalences#equals()} * otherwise. */ - @GwtIncompatible("To be supported") CacheBuilder<K, V> valueEquivalence(Equivalence<Object> equivalence) { checkState(valueEquivalence == null, "value equivalence was already set to %s", valueEquivalence); @@ -350,23 +305,11 @@ public final class CacheBuilder<K, V> { * higher value than you need can waste space and time, and a significantly lower value can lead * to thread contention. But overestimates and underestimates within an order of magnitude do not * usually have much noticeable impact. A value of one permits only one thread to modify the cache - * at a time, but since read operations and cache loading computations can proceed concurrently, - * this still yields higher concurrency than full synchronization. - * - * <p> Defaults to 4. <b>Note:</b>The default may change in the future. If you care about this - * value, you should always choose it explicitly. - * - * <p>The current implementation uses the concurrency level to create a fixed number of hashtable - * segments, each governed by its own write lock. The segment lock is taken once for each explicit - * write, and twice for each cache loading computation (once prior to loading the new value, - * and once after loading completes). Much internal cache management is performed at the segment - * granularity. For example, access queues and write queues are kept per segment when they are - * required by the selected eviction algorithm. As such, when writing unit tests it is not - * uncommon to specify {@code concurrencyLevel(1)} in order to achieve more deterministic eviction - * behavior. + * at a time, but since read operations can proceed concurrently, this still yields higher + * concurrency than full synchronization. Defaults to 4. * - * <p>Note that future implementations may abandon segment locking in favor of more advanced - * concurrency controls. + * <p><b>Note:</b>The default may change in the future. If you care about this value, you should + * always choose it explicitly. * * @throws IllegalArgumentException if {@code concurrencyLevel} is nonpositive * @throws IllegalStateException if a concurrency level was already set @@ -392,11 +335,9 @@ public final class CacheBuilder<K, V> { * <p>When {@code size} is zero, elements will be evicted immediately after being loaded into the * cache. This can be useful in testing, or to disable caching temporarily without a code change. * - * <p>This feature cannot be used in conjunction with {@link #maximumWeight}. - * * @param size the maximum size of the cache * @throws IllegalArgumentException if {@code size} is negative - * @throws IllegalStateException if a maximum size or weight was already set + * @throws IllegalStateException if a maximum size was already set */ public CacheBuilder<K, V> maximumSize(long size) { checkState(this.maximumSize == UNSET_INT, "maximum size was already set to %s", @@ -423,17 +364,11 @@ public final class CacheBuilder<K, V> { * cache. This can be useful in testing, or to disable caching temporarily without a code * change. * - * <p>Note that weight is only used to determine whether the cache is over capacity; it has no - * effect on selecting which entry should be evicted next. - * - * <p>This feature cannot be used in conjunction with {@link #maximumSize}. - * - * @param weight the maximum total weight of entries the cache may contain - * @throws IllegalArgumentException if {@code weight} is negative - * @throws IllegalStateException if a maximum weight or size was already set + * @param weight the maximum weight the cache may contain + * @throws IllegalArgumentException if {@code size} is negative + * @throws IllegalStateException if a maximum size was already set * @since 11.0 */ - @GwtIncompatible("To be supported") public CacheBuilder<K, V> maximumWeight(long weight) { checkState(this.maximumWeight == UNSET_INT, "maximum weight was already set to %s", this.maximumWeight); @@ -472,7 +407,6 @@ public final class CacheBuilder<K, V> { * @throws IllegalStateException if a maximum size was already set * @since 11.0 */ - @GwtIncompatible("To be supported") public <K1 extends K, V1 extends V> CacheBuilder<K1, V1> weigher( Weigher<? super K1, ? super V1> weigher) { checkState(this.weigher == null); @@ -502,6 +436,15 @@ public final class CacheBuilder<K, V> { } /** + * Specifies that each key (not value) stored in the cache should be strongly referenced. + * + * @throws IllegalStateException if the key strength was already set + */ + CacheBuilder<K, V> strongKeys() { + return setKeyStrength(Strength.STRONG); + } + + /** * Specifies that each key (not value) stored in the cache should be wrapped in a {@link * WeakReference} (by default, strong references are used). * @@ -530,6 +473,15 @@ public final class CacheBuilder<K, V> { } /** + * Specifies that each value (not key) stored in the cache should be strongly referenced. + * + * @throws IllegalStateException if the value strength was already set + */ + CacheBuilder<K, V> strongValues() { + return setValueStrength(Strength.STRONG); + } + + /** * Specifies that each value (not key) stored in the cache should be wrapped in a * {@link WeakReference} (by default, strong references are used). * @@ -657,9 +609,8 @@ public final class CacheBuilder<K, V> { * {@link CacheLoader#reload}. * * <p>As the default implementation of {@link CacheLoader#reload} is synchronous, it is - * recommended that users of this method override {@link CacheLoader#reload} with an asynchronous - * implementation; otherwise refreshes will be performed during unrelated cache read and write - * operations. + * recommended that users of this method override {@link CacheLoader#reload} with an asynchrnous + * implementation; otherwise refreshes will block other cache operations. * * <p>Currently automatic refreshes are performed when the first stale request for an entry * occurs. The request triggering refresh will make a blocking call to {@link CacheLoader#reload} @@ -675,8 +626,7 @@ public final class CacheBuilder<K, V> { * @throws IllegalStateException if the refresh interval was already set * @since 11.0 */ - @Beta - @GwtIncompatible("To be supported (synchronously).") + @GwtIncompatible("To be supported") public CacheBuilder<K, V> refreshAfterWrite(long duration, TimeUnit unit) { checkNotNull(unit); checkState(refreshNanos == UNSET_INT, "refresh was already set to %s ns", refreshNanos); @@ -698,6 +648,7 @@ public final class CacheBuilder<K, V> { * * @throws IllegalStateException if a ticker was already set */ + @GwtIncompatible("To be supported") public CacheBuilder<K, V> ticker(Ticker ticker) { checkState(this.ticker == null); this.ticker = checkNotNull(ticker); @@ -712,27 +663,34 @@ public final class CacheBuilder<K, V> { } /** - * Specifies a listener instance that caches should notify each time an entry is removed for any - * {@linkplain RemovalCause reason}. Each cache created by this builder will invoke this listener - * as part of the routine maintenance described in the class documentation above. - * - * <p><b>Warning:</b> after invoking this method, do not continue to use <i>this</i> cache - * builder reference; instead use the reference this method <i>returns</i>. At runtime, these - * point to the same instance, but only the returned reference has the correct generic type - * information so as to ensure type safety. For best results, use the standard method-chaining - * idiom illustrated in the class documentation above, configuring a builder and building your - * cache in a single statement. Failure to heed this advice can result in a {@link - * ClassCastException} being thrown by a cache operation at some <i>undefined</i> point in the - * future. - * - * <p><b>Warning:</b> any exception thrown by {@code listener} will <i>not</i> be propagated to - * the {@code Cache} user, only logged via a {@link Logger}. - * - * @return the cache builder reference that should be used instead of {@code this} for any - * remaining configuration and cache building + * Specifies a listener instance, which all caches built using this {@code CacheBuilder} will + * notify each time an entry is removed from the cache by any means. + * + * <p>Each cache built by this {@code CacheBuilder} after this method is called invokes the + * supplied listener after removing an element for any reason (see removal causes in {@link + * RemovalCause}). It will invoke the listener as part of the routine maintenance described + * in the class javadoc. + * + * <p><b>Note:</b> <i>all exceptions thrown by {@code listener} will be logged (using + * {@link java.util.logging.Logger})and then swallowed</i>. + * + * <p><b>Important note:</b> Instead of returning <em>this</em> as a {@code CacheBuilder} + * instance, this method returns {@code CacheBuilder<K1, V1>}. From this point on, either the + * original reference or the returned reference may be used to complete configuration and build + * the cache, but only the "generic" one is type-safe. That is, it will properly prevent you from + * building caches whose key or value types are incompatible with the types accepted by the + * listener already provided; the {@code CacheBuilder} type cannot do this. For best results, + * simply use the standard method-chaining idiom, as illustrated in the documentation at top, + * configuring a {@code CacheBuilder} and building your {@link Cache} all in a single statement. + * + * <p><b>Warning:</b> if you ignore the above advice, and use this {@code CacheBuilder} to build + * a cache whose key or value type is incompatible with the listener, you will likely experience + * a {@link ClassCastException} at some <i>undefined</i> point in the future. + * * @throws IllegalStateException if a removal listener was already set */ @CheckReturnValue + @GwtIncompatible("To be supported") public <K1 extends K, V1 extends V> CacheBuilder<K1, V1> removalListener( RemovalListener<? super K1, ? super V1> listener) { checkState(this.removalListener == null); @@ -751,15 +709,11 @@ public final class CacheBuilder<K, V> { } /** - * Enable the accumulation of {@link CacheStats} during the operation of the cache. Without this - * {@link Cache#stats} will return zero for all statistics. Note that recording stats requires - * bookkeeping to be performed with each operation, and thus imposes a performance penalty on - * cache operation. - * - * @since 12.0 (previously, stats collection was automatic) + * Disable the accumulation of {@link CacheStats} during the operation of the cache. */ - public CacheBuilder<K, V> recordStats() { - statsCounterSupplier = CACHE_STATS_COUNTER; + CacheBuilder<K, V> disableStats() { + checkState(statsCounterSupplier == CACHE_STATS_COUNTER); + statsCounterSupplier = NULL_STATS_COUNTER; return this; } @@ -834,11 +788,12 @@ public final class CacheBuilder<K, V> { if (concurrencyLevel != UNSET_INT) { s.add("concurrencyLevel", concurrencyLevel); } - if (maximumSize != UNSET_INT) { - s.add("maximumSize", maximumSize); - } if (maximumWeight != UNSET_INT) { - s.add("maximumWeight", maximumWeight); + if (weigher == null) { + s.add("maximumSize", maximumWeight); + } else { + s.add("maximumWeight", maximumWeight); + } } if (expireAfterWriteNanos != UNSET_INT) { s.add("expireAfterWrite", expireAfterWriteNanos + "ns"); |