001package org.cache2k; 002 003/* 004 * #%L 005 * cache2k API 006 * %% 007 * Copyright (C) 2000 - 2016 headissue GmbH, Munich 008 * %% 009 * Licensed under the Apache License, Version 2.0 (the "License"); 010 * you may not use this file except in compliance with the License. 011 * You may obtain a copy of the License at 012 * 013 * http://www.apache.org/licenses/LICENSE-2.0 014 * 015 * Unless required by applicable law or agreed to in writing, software 016 * distributed under the License is distributed on an "AS IS" BASIS, 017 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 018 * See the License for the specific language governing permissions and 019 * limitations under the License. 020 * #L% 021 */ 022 023import org.cache2k.configuration.Cache2kConfiguration; 024import org.cache2k.configuration.CacheTypeCapture; 025import org.cache2k.configuration.CacheType; 026import org.cache2k.configuration.ConfigurationSection; 027import org.cache2k.configuration.ConfigurationSectionBuilder; 028import org.cache2k.configuration.CustomizationReferenceSupplier; 029import org.cache2k.expiry.ExpiryPolicy; 030import org.cache2k.event.CacheEntryOperationListener; 031import org.cache2k.integration.AdvancedCacheLoader; 032import org.cache2k.integration.CacheLoader; 033import org.cache2k.integration.CacheWriter; 034import org.cache2k.integration.ExceptionPropagator; 035import org.cache2k.integration.ResiliencePolicy; 036 037import java.lang.reflect.ParameterizedType; 038import java.lang.reflect.Type; 039import java.util.concurrent.Executor; 040import java.util.concurrent.TimeUnit; 041 042/** 043 * Builder to create a {@link Cache} instance. The usage is: 044 * 045 * <pre>{@code 046 * Cache<Long, List<String>> c = 047 * new Cache2kBuilder<Long, List<String>>() {} 048 * .name("myCache") 049 * .eternal(true) 050 * .build(); 051 * }</pre> 052 * 053 * <p>Caches belong to a cache manager. If no cache manager is set explicitly via {@link #manager} the 054 * default cache manager will be used, as defined by {@link CacheManager#getInstance()}. 055 * 056 * <p>To create a cache from a known configuration in a specified cache manager, use: 057 * 058 * <pre>{@code 059 * CacheManager manager = ... 060 * CacheConfiguration<Long, List<String>> config = ... 061 * 062 * Cache<Long, List<String>> c = 063 * Cache2kBuilder.of(config) 064 * .manager(manager) 065 * .build(); 066 * }</pre> 067 * 068 * <p>To create a cache without type parameters or {@code Cache<Object,Object>}, use {@link Cache2kBuilder#forUnknownTypes()}. 069 * 070 * @author Jens Wilke 071 * @since 1.0 072 */ 073public class Cache2kBuilder<K, V> { 074 075 private static final String MSG_NO_TYPES = "Use Cache2kBuilder.forUnknownTypes(), to construct a builder with no key and value types"; 076 077 /** 078 * Create a new cache builder for a cache that has no type restrictions 079 * or to set the type information later via the builder methods {@link #keyType} or 080 * {@link #valueType}. 081 */ 082 public static Cache2kBuilder forUnknownTypes() { 083 return new Cache2kBuilder(null, null); 084 } 085 086 /** 087 * Create a new cache builder for key and value types are classes with no generic parameters. 088 * 089 * @see #keyType(Class) 090 * @see #valueType(Class) 091 */ 092 public static <K,T> Cache2kBuilder<K,T> of(Class<K> _keyType, Class<T> _valueType) { 093 return new Cache2kBuilder<K, T>(CacheTypeCapture.of(_keyType), CacheTypeCapture.of(_valueType)); 094 } 095 096 /** 097 * Create a builder from the configuration. 098 */ 099 public static <K,T> Cache2kBuilder<K, T> of(Cache2kConfiguration<K, T> c) { 100 Cache2kBuilder<K,T> cb = new Cache2kBuilder<K, T>(c); 101 return cb; 102 } 103 104 private CacheType<K> keyType; 105 private CacheType<V> valueType; 106 private Cache2kConfiguration<K,V> config = null; 107 private CacheManager manager = null; 108 109 private Cache2kBuilder(Cache2kConfiguration<K,V> cfg) { 110 withConfig(cfg); 111 } 112 113 /** 114 * Constructor to override for the usage pattern: 115 * 116 * <pre>{@code 117 * Cache<Long, List<String>> c = 118 * new Cache2kBuilder<Long, List<String>>() {} 119 * .name("myCache") 120 * .eternal(true) 121 * .build(); 122 * }</pre> 123 * 124 * The builder extracts the generic type parameters from the anonymous subclass. 125 */ 126 @SuppressWarnings("unchecked") 127 protected Cache2kBuilder() { 128 Type t = this.getClass().getGenericSuperclass(); 129 if (!(t instanceof ParameterizedType)) { 130 throw new IllegalArgumentException(MSG_NO_TYPES); 131 } 132 Type[] _types = ((ParameterizedType) t).getActualTypeArguments(); 133 keyType = (CacheType<K>) CacheTypeCapture.of(_types[0]).getBeanRepresentation(); 134 valueType = (CacheType<V>) CacheTypeCapture.of(_types[1]).getBeanRepresentation(); 135 if (Object.class.equals(keyType.getType()) && 136 Object.class.equals(valueType.getType())) { 137 throw new IllegalArgumentException(MSG_NO_TYPES); 138 } 139 } 140 141 private Cache2kBuilder(CacheType<K> _keyType, CacheType<V> _valueType) { 142 keyType = _keyType; 143 valueType = _valueType; 144 } 145 146 private void withConfig(Cache2kConfiguration<K,V> cfg) { 147 config = cfg; 148 } 149 150 private Cache2kConfiguration<K, V> config() { 151 if (config == null) { 152 if (manager == null) { 153 manager = CacheManager.getInstance(); 154 } 155 config = CacheManager.PROVIDER.getDefaultConfiguration(manager); 156 if (keyType != null) { 157 config.setKeyType(keyType); 158 } 159 if (valueType != null) { 160 config.setValueType(valueType); 161 } 162 } 163 return config; 164 } 165 166 /** 167 * The manager, the created cache will belong to. If this is set, it must be the 168 * first method called. 169 * 170 * @param manager The manager the created cache should belong to, 171 * or {@code null} if the default cache manager should be used 172 * @throws IllegalStateException if the manager is not provided immediately after the builder is created. 173 */ 174 public final Cache2kBuilder<K, V> manager(CacheManager manager) { 175 if (this.manager != null) { 176 throw new IllegalStateException("manager() must be first operation on builder."); 177 } 178 this.manager = manager; 179 return this; 180 } 181 182 /** 183 * The used type of the cache key. A suitable cache key must provide a useful 184 * {@code equals} and {@code hashCode} method. Arrays are not valid for cache keys. 185 * 186 * @throws IllegalArgumentException in case the type is illegal 187 * @see CacheType for a general discussion on types 188 */ 189 public final <K2> Cache2kBuilder<K2, V> keyType(Class<K2> t) { 190 config().setKeyType(t); 191 return (Cache2kBuilder<K2, V>) this; 192 } 193 194 /** 195 * Sets the value type to use. Arrays are not supported. 196 * 197 * @throws IllegalArgumentException in case the type is illegal 198 * @see CacheType for a general discussion on types 199 */ 200 public final <T2> Cache2kBuilder<K, T2> valueType(Class<T2> t) { 201 config().setValueType(t); 202 return (Cache2kBuilder<K, T2>) this; 203 } 204 205 /** 206 * The used type of the cache key. A suitable cache key must provide a useful 207 * {@code equals} and {@code hashCode} method. Arrays are not valid for cache keys. 208 * 209 * @throws IllegalArgumentException in case the type is illegal 210 * @see CacheType for a general discussion on types 211 */ 212 public final <K2> Cache2kBuilder<K2, V> keyType(CacheType<K2> t) { 213 config().setKeyType(t); 214 return (Cache2kBuilder<K2, V>) this; 215 } 216 217 /** 218 * Sets the value type to use. Arrays are not supported. 219 * 220 * @throws IllegalArgumentException in case the type is illegal 221 * @see CacheType for a general discussion on types 222 */ 223 public final <T2> Cache2kBuilder<K, T2> valueType(CacheType<T2> t) { 224 config().setValueType(t); 225 return (Cache2kBuilder<K, T2>) this; 226 } 227 228 /** 229 * Constructs a cache name out of the class name, a field name and a unique name identifying the 230 * component in the application. Result example: {@code webImagePool~com.example.ImagePool.id2Image} 231 * 232 * <p>See {@link #name(String)} for a general discussion about cache names. 233 * 234 * @param _uniqueName unique name differentiating multiple components of the same type. 235 * May be {@code null}. 236 * @see #name(String) 237 */ 238 public final Cache2kBuilder<K, V> name(String _uniqueName, Class<?> _class, String _fieldName) { 239 if (_fieldName == null) { 240 throw new NullPointerException(); 241 } 242 if (_uniqueName == null) { 243 return name(_class, _fieldName); 244 } 245 config().setName(_uniqueName + '~' + _class.getName() + "." + _fieldName); 246 return this; 247 } 248 249 /** 250 * Constructs a cache name out of the class name and field name. Result example: 251 * {@code com.example.ImagePool.id2Image} 252 * 253 * <p>See {@link #name(String)} for a general discussion about cache names. 254 * 255 * @see #name(String) 256 */ 257 public final Cache2kBuilder<K, V> name(Class<?> _class, String _fieldName) { 258 if (_fieldName == null) { 259 throw new NullPointerException(); 260 } 261 config().setName(_class.getName() + "." + _fieldName); 262 return this; 263 } 264 265 /** 266 * Sets a cache name from the fully qualified class name. 267 * 268 * <p>See {@link #name(String)} for a general discussion about cache names. 269 * 270 * @see #name(String) 271 */ 272 public final Cache2kBuilder<K, V> name(Class<?> _class) { 273 config().setName(_class.getName()); 274 return this; 275 } 276 277 /** 278 * Sets the name of a cache. If a name is specified it must be ensured it is unique within 279 * the cache manager. Cache names are used at several places to have a unique ID of a cache. 280 * For example, for referencing additional configuration or to register JMX beans. 281 * 282 * <p>If a name is not specified the cache generates a name automatically. The name is 283 * inferred from the call stack trace and contains the simple class name, the method and 284 * the line number of the of the caller to <code>build()</code>. The name also contains 285 * a random number. Automatically generated names don't allow reliable management, logging and 286 * additional configuration of caches. If no name is set, {@link #build()} will always create 287 * a new cache with a new unique name within the cache manager. Automatically generated 288 * cache names start with the character <code>'_'</code> as prefix to separate the names from the 289 * usual class name space. 290 * 291 * <p>In case of a name collision the cache is generating a unique name by adding a counter value. 292 * This behavior may change. 293 * 294 * <p>Allowed characters for a cache name, are URL non-reserved characters, 295 * these are: <code>[A-Z]</code>, <code>[a-z]</code>, <code>[0-9]</code> and <code>[~-_.]</code>, 296 * see RFC3986 as well as the characters: <code>[()]</code>. The characters <code>[@, ]</code> are supported 297 * as well, but should be avoided. 298 * 299 * <p>The reason for restricting the characters in names, is that the names may be used to derive 300 * other resource names from it, e.g. for file based storage. The cache might not enforce the allowed 301 * character set for efficiency reasons. 302 * 303 * <p>The method is overloaded with variants to provide a naming convention of names. 304 * 305 * <p>For brevity within log messages and other displays the cache name may be 306 * shortened if the manager name is included as prefix. 307 * 308 * @see Cache#getName() 309 */ 310 public final Cache2kBuilder<K, V> name(String v) { 311 config().setName(v); 312 return this; 313 } 314 315 /** 316 * Expired data is kept in the cache until the entry is evicted. This consumes memory, 317 * but if the data is accessed again the previous data can be used by the cache loader 318 * for optimizing (e.g. if-modified-since for a HTTP request). Default value: false 319 * 320 * @see AdvancedCacheLoader 321 */ 322 public final Cache2kBuilder<K, V> keepDataAfterExpired(boolean v) { 323 config().setKeepDataAfterExpired(v); 324 return this; 325 } 326 327 /** 328 * The maximum number of entries hold by the cache. When the maximum size is reached, by 329 * inserting new entries, the cache eviction algorithm will remove one or more entries 330 * to keep the size within the configured limit. 331 * 332 * <p>The value {@code Long.MAX_VALUE} means the capacity is not limited. 333 * 334 * <p>The default value is: 2000. The default value is conservative, so the application 335 * will usually run stable without tuning or setting a reasonable size. 336 */ 337 public final Cache2kBuilder<K, V> entryCapacity(long v) { 338 config().setEntryCapacity(v); 339 return this; 340 } 341 342 /** 343 * When set to true, cached values do not expire by time. Entries will need to be removed 344 * from the cache explicitly or will be evicted if capacity constraints are reached. 345 346 * <p>Setting eternal to false signals that the data should expire, but there is no 347 * predefined expiry value at programmatic level. This value needs to be set by other 348 * means, e.g. within a configuration file. 349 * 350 * <p>The default behavior of the cache is identical to the setting eternal, meaning no 351 * expiry. 352 * 353 * <p>Exceptions: If set to eternal with default setting and if there is no 354 * explicit expiry configured for exceptions with {@link #retryInterval(long, TimeUnit)}, 355 * exceptions will not be cached and expire immediately. 356 * 357 * @throws IllegalArgumentException in case a previous setting is reset 358 */ 359 public final Cache2kBuilder<K, V> eternal(boolean v) { 360 config().setEternal(v); 361 return this; 362 } 363 364 /** 365 * If an exceptions gets thrown by the cache loader, suppress it if there is 366 * a previous value. When this is active, and an exception was suppressed 367 * the expiry is determined by {@link #retryInterval(long, TimeUnit)}. 368 * 369 * <p>Setting this to false, will disable suppression or caching (aka resilience). 370 * Default value: true 371 * 372 * <p>Additional information can be found under <b>resilience</b> in 373 * the documentation. 374 */ 375 public final Cache2kBuilder<K, V> suppressExceptions(boolean v) { 376 config().setSuppressExceptions(v); 377 return this; 378 } 379 380 381 /** 382 * Time duration after insert or updated an cache entry expires. 383 * To switch off time based expiry use {@link #eternal(boolean)}. 384 * 385 * <p>If an {@link ExpiryPolicy} is specified, the maximum expiry duration 386 * will not exceed the value that is specified here. 387 * 388 * <p>A value of {@code 0} means every entry should expire immediately. Low values or 389 * {@code 0} together with read through operation mode with a {@link CacheLoader} should be 390 * avoided in production environments. 391 * 392 * @throws IllegalArgumentException if {@link #eternal(boolean)} was set to true 393 */ 394 public final Cache2kBuilder<K, V> expireAfterWrite(long v, TimeUnit u) { 395 config().setExpireAfterWrite(u.toMillis(v)); 396 return this; 397 } 398 399 public final Cache2kBuilder<K, V> exceptionPropagator(ExceptionPropagator<K> ep) { 400 config().setExceptionPropagator(wrapCustomizationInstance(ep)); 401 return this; 402 } 403 404 /** Wraps to factory but passes on nulls. */ 405 private static <T> CustomizationReferenceSupplier<T> wrapCustomizationInstance(T obj) { 406 if (obj == null) { return null; } 407 return new CustomizationReferenceSupplier<T>(obj); 408 } 409 410 public final Cache2kBuilder<K, V> loader(CacheLoader<K, V> l) { 411 config().setLoader(wrapCustomizationInstance(l)); 412 return this; 413 } 414 415 public final Cache2kBuilder<K, V> loader(AdvancedCacheLoader<K, V> l) { 416 config().setAdvancedLoader(wrapCustomizationInstance(l)); 417 return this; 418 } 419 420 public final Cache2kBuilder<K, V> writer(CacheWriter<K, V> w) { 421 config().setWriter(wrapCustomizationInstance(w)); 422 return this; 423 } 424 425 /** 426 * Add a listener. The listeners will be executed in a synchronous mode, meaning, 427 * further processing for an entry will stall until a registered listener is executed. 428 * The expiry will be always executed asynchronously. 429 * 430 * @throws IllegalArgumentException if an identical listener is already added. 431 * @param listener The listener to add 432 */ 433 public final Cache2kBuilder<K, V> addListener(CacheEntryOperationListener<K,V> listener) { 434 boolean _inserted = config().getListeners().add(wrapCustomizationInstance(listener)); 435 if (!_inserted) { 436 throw new IllegalArgumentException("Listener already added"); 437 } 438 return this; 439 } 440 441 /** 442 * A set of listeners. Listeners added in this collection will be 443 * executed in a synchronous mode, meaning, further processing for 444 * an entry will stall until a registered listener is executed. 445 * 446 * @throws IllegalArgumentException if an identical listener is already added. 447 * @param listener The listener to add 448 */ 449 public final Cache2kBuilder<K,V> addAsyncListener(CacheEntryOperationListener<K,V> listener) { 450 boolean _inserted = config().getAsyncListeners().add(wrapCustomizationInstance(listener)); 451 if (!_inserted) { 452 throw new IllegalArgumentException("Listener already added"); 453 } 454 return this; 455 } 456 457 /** 458 * Set expiry policy to use. 459 * 460 * <p>If this is specified the maximum expiry time is still limited to the value in 461 * {@link #expireAfterWrite}. If {@link #expireAfterWrite(long, java.util.concurrent.TimeUnit)} 462 * is set to 0 then expiry calculation is not used, all entries expire immediately. 463 * 464 * <p>If no maximum expiry is specified via {@link #expireAfterWrite} at leas the 465 * {@link #resilienceDuration} needs to be specified, if resilience should be enabled. 466 */ 467 public final Cache2kBuilder<K, V> expiryPolicy(ExpiryPolicy<K, V> c) { 468 config().setExpiryPolicy(wrapCustomizationInstance(c)); 469 return this; 470 } 471 472 /** 473 * When true, enable background refresh / refresh ahead. After the expiry time of a value is reached, 474 * the loader is invoked to fetch a fresh value. The old value will be returned by the cache, although 475 * it is expired, and will be replaced by the new value, once the loader is finished. In the case 476 * there are not enough loader threads available, the value will expire immediately and 477 * the next {@code get()} request will trigger the load. 478 * 479 * <p>Once refreshed, the entry is in a trail period. If it is not accessed until the next 480 * expiry, no refresh will be done and the entry expires regularly. This means that the 481 * time an entry stays within the trail period is determined by the configured expiry time 482 * or the the {@code ExpiryPolicy}. In case an entry is not accessed any more it needs to 483 * reach the expiry time twice before removed from the cache. 484 * 485 * <p>The number of threads used to do the refresh are configured via 486 * {@link #loaderThreadCount(int)} 487 * 488 * @see CacheLoader 489 * @see #loaderThreadCount(int) 490 */ 491 public final Cache2kBuilder<K, V> refreshAhead(boolean f) { 492 config().setRefreshAhead(f); 493 return this; 494 } 495 496 /** 497 * By default the expiry time is not exact, which means, a value might be visible a few 498 * milliseconds after the time of expiry. The time lag depends on the system load. 499 * Switching to true, means that values will not be visible when the time is reached that 500 * {@link ExpiryPolicy} returned. 501 */ 502 public final Cache2kBuilder<K, V> sharpExpiry(boolean f) { 503 config().setSharpExpiry(f); 504 return this; 505 } 506 507 /** 508 * If no separate executor is set via {@link #loaderExecutor(Executor)} the cache will 509 * create a separate thread pool used exclusively by it. Defines the maximum number of threads 510 * this cache should use for calls to the {@link CacheLoader}. The default is one thread 511 * per available CPU. 512 * 513 * <p>If a separate executor is defined the parameter has no effect. 514 * 515 * @see #loaderExecutor(Executor) 516 * @see #prefetchExecutor(Executor) 517 */ 518 public final Cache2kBuilder<K, V> loaderThreadCount(int v) { 519 config().setLoaderThreadCount(v); 520 return this; 521 } 522 523 /** 524 * Ensure that the cache value is stored via direct object reference and that 525 * no serialization takes place. Cache clients leveraging the fact that an in heap 526 * cache stores object references directly should set this value. 527 * 528 * <p>If this value is not set to true this means: The key and value objects need to have a 529 * defined serialization mechanism and the cache may choose to transfer off the heap. 530 * For cache2k version 1.0 this value has no effect. It should be 531 * used by application developers to future proof the applications with upcoming versions. 532 */ 533 public final Cache2kBuilder<K, V> storeByReference(boolean v) { 534 config().setStoreByReference(v); 535 return this; 536 } 537 538 /** 539 * If a loader exception happens, this is the time interval after a 540 * retry attempt is made. If not specified, 10% of {@link #maxRetryInterval}. 541 */ 542 public final Cache2kBuilder<K, V> retryInterval(long v, TimeUnit u) { 543 config().setRetryInterval(u.toMillis(v)); 544 return this; 545 } 546 547 /** 548 * If a loader exception happens, this is the maximum time interval after a 549 * retry attempt is made. For retries an exponential backoff algorithm is used. 550 * It starts with the retry time and then increases the time to the maximum 551 * according to an exponential pattern. 552 * 553 * <p>By default identical to {@link #resilienceDuration} 554 */ 555 public final Cache2kBuilder<K, V> maxRetryInterval(long v, TimeUnit u) { 556 config().setMaxRetryInterval(u.toMillis(v)); 557 return this; 558 } 559 560 /** 561 * Time span the cache will suppress loader exceptions if a value is available from 562 * a previous load. After the time span is passed the cache will start propagating 563 * loader exceptions. If {@link #suppressExceptions} is switched off, this setting 564 * has no effect. 565 * 566 * <p>Defaults to {@link #expireAfterWrite}. If {@link #suppressExceptions} 567 * is switched off, this setting has no effect. 568 */ 569 public final Cache2kBuilder<K, V> resilienceDuration(long v, TimeUnit u) { 570 config().setResilienceDuration(u.toMillis(v)); 571 return this; 572 } 573 574 /** 575 * Sets a custom resilience policy to control the cache behavior in the presence 576 * of exceptions from the loader. A specified policy will be ignored if 577 * {@link #expireAfterWrite} is set to 0. 578 */ 579 public final Cache2kBuilder<K,V> resiliencePolicy(ResiliencePolicy<K,V> v) { 580 config().setResiliencePolicy(wrapCustomizationInstance(v)); 581 return this; 582 } 583 584 /** 585 * Add a new configuration sub section. 586 * 587 * @see org.cache2k.configuration.ConfigurationWithSections 588 */ 589 public final Cache2kBuilder<K, V> with(ConfigurationSectionBuilder<? extends ConfigurationSection>... sectionBuilders) { 590 for (ConfigurationSectionBuilder<? extends ConfigurationSection> b : sectionBuilders) { 591 config().getSections().add(b.buildConfigurationSection()); 592 } 593 return this; 594 } 595 596 /** 597 * To increase performance cache2k optimizes the eviction and does eviction in 598 * greater chunks. With strict eviction, the eviction is done for one entry 599 * as soon as the capacity constraint is met. This is primarily used for 600 * testing and evaluation purposes. 601 */ 602 public final Cache2kBuilder<K,V> strictEviction(boolean flag) { 603 config().setStrictEviction(flag); 604 return this; 605 } 606 607 /** 608 * When {@code true}, {@code null} values are allowed in the cache. In the default configuration 609 * {@code null} values are prohibited. 610 * 611 * <p>See the chapter in the user guide for details on {@code null} values. 612 * 613 * @see CacheLoader#load(Object) 614 * @see ExpiryPolicy#calculateExpiryTime(Object, Object, long, CacheEntry) 615 */ 616 public final Cache2kBuilder<K,V> permitNullValues(boolean flag) { 617 config().setPermitNullValues(flag); 618 return this; 619 } 620 621 /** 622 * By default statistic gathering is enabled. Set true to disable statistics. Disabling statistics 623 * will minimize overhead and switch off any counters that are present for informational purposes only. 624 * Counters that don't have a significant overhead or are maintained in any case are still available. 625 * The setting doesn't affect whether JMX values are exposed or not. 626 */ 627 public final Cache2kBuilder<K,V> disableStatistics(boolean flag) { 628 config().setDisableStatistics(flag); 629 return this; 630 } 631 632 /** 633 * Number of eviction segments. The default is one or two if the available processor 634 * count is more than one. In case the workload has lots of concurrent inserts or eviction 635 * the segment count may be increased if the cache eviction becomes the bottle neck. 636 * A value higher then the processor count is ineffective. Setting a higher value has 637 * a negative impact on the eviction efficiency. There will be hardly any application with 638 * a little positive effect when this parameter is set. Usual applications that do mostly 639 * concurrent reads, do not need an increase. 640 */ 641 public final Cache2kBuilder<K,V> evictionSegmentCount(int v) { 642 config().setEvictionSegmentCount(v); 643 return this; 644 } 645 646 /** 647 * Thread pool / executor service to use for asynchronous load operations. If no executor is specified 648 * the cache will create a thread pool, if needed. 649 * 650 * @see #loaderThreadCount(int) 651 * @see #prefetchExecutor(Executor) 652 */ 653 public final Cache2kBuilder<K,V> loaderExecutor(Executor v) { 654 config().setLoaderExecutor(new CustomizationReferenceSupplier<Executor>(v)); 655 return this; 656 } 657 658 /** 659 * Thread pool / executor service to use for refresh ahead and prefetch operations. If not specified the 660 * same refresh ahead operation will use the thread pool defined by {@link #loaderExecutor(Executor)} 661 * or a cache local pool is created. 662 * 663 * @see #loaderThreadCount(int) 664 * @see #loaderExecutor(Executor) 665 */ 666 public final Cache2kBuilder<K,V> prefetchExecutor(Executor v) { 667 config().setPrefetchExecutor(new CustomizationReferenceSupplier<Executor>(v)); 668 return this; 669 } 670 671 /** 672 * Returns the configuration object this builder operates on. Changes to the configuration also 673 * will influence the created cache when {@link #build()} is called. The method does not 674 * return the effective configuration if additional external/XML configuration is present, since 675 * this is applied when {@code build} is called. On the other hand, the method can be used 676 * to inspect the effective configuration after {@code build} completed. 677 * 678 * @return configuration objects with the parameters set in the builder. 679 */ 680 public final Cache2kConfiguration<K,V> toConfiguration() { 681 return config(); 682 } 683 684 /** 685 * Builds a cache with the specified configuration parameters. 686 * The builder reused to build caches with similar or identical 687 * configuration. The builder is not thread safe. 688 * 689 * @throws IllegalArgumentException if a cache of the same name is already active in the cache manager 690 */ 691 public final Cache<K, V> build() { 692 return CacheManager.PROVIDER.createCache(manager, config()); 693 } 694 695}