19 Haziran 2019 Çarşamba

Caffeine AsyncCache Arayüzü

Örnek
Şöyle yaparız.
AsyncCache<String, Cat> asyncCache = Caffeine.newBuilder()
        .expireAfterWrite(1, TimeUnit.HOURS)
        .recordStats()
        .maximumSize(100)
        .buildAsync();

Cache<String, Cat> cache = Caffeine.newBuilder()
        .expireAfterWrite(1, TimeUnit.HOURS)
        .maximumSize(100)
        .recordStats()
        .build();

18 Haziran 2019 Salı

RateLimiter Sınıfı

Giriş
Şu satırı dahil ederiz.
import com.google.common.util.concurrent.RateLimiter;
Bu sınıfla ile kaynaklara erişime sınırlama konuluyor. Bu sınıfa aynı zamanda "Message Throttling" da deniliyor.

Kaynaklara Sınır Koymak
Rate Limiting Algorithms yazısına taşıdım

Guava Ne Kullanıyor?
Guava Spike Control Policy yöntemini kullanıyor. Kalıtım şöyle
RateLimiter <- SmoothRateLimiter <- SmoothWarmingUp 
                                                        <- SmoothBursty
Açıklaması şöyle
The configured rate is distributed evenly across the interval. (more like a sliding window)
Sınıfın Hatası Var
Açıklaması şöyle.
It seems like Guava RateLimiter can only work up to a limit of 1,000,000 aquire calls per second. If you try to do 1,000,001 aquire calls per second the call to aquire will not wait at all (return value of aquire() is always 0.0) -> no throttling occurs.
Under Utilization
Açıklaması şöyle
A SmoothRateLimiter has four member variables:

storedPermits - used to model past underutilization as described in Design section.
maxPermits - maximum number of storedPermits.
stableIntervalMicros - the interval between two requests at the stable rate. Its value should be 1 / rate.
nextFreeTicketMicros - the time when next permit can be granted. It is updated after each permit is granted.
Eğer SmoothRateLimiter sınıfındaki kod şöyle. Eğer under utilization varsa storedPersmit alanı en fazla maxPersmits olacak kadar tekrar dolduruluyor. storedPermits alanı doluysa, RateLimiter bu alan tekrar 0 oluncaya kadar acqiure() metodlarına hemen cevap veriyor. Yani beklemiyor. Bu da en bazı durumlarda RateLimiter sınıfının kendisini tekrar toparlayıncaya kadar bazı istekleri geçirdiği anlamına gelir.
void resync(long nowMicros) {
  // if nextFreeTicket is in the past, resync to now
  if (nowMicros > nextFreeTicketMicros) {
    double newPermits = (nowMicros - nextFreeTicketMicros) / coolDownIntervalMicros();
    storedPermits = min(maxPermits, storedPermits + newPermits);
    nextFreeTicketMicros = nowMicros;
  }
}
C++
Benzer bir şeyi C++ ile şöyle yaparız
#include <chrono>

class RateController {
  using clk_t        = std::chrono::system_clock;

public:
  RateController(unsigned limit, long time_slice_seconds)
      : n_(limit), time_slice_(time_slice_seconds) {}

  bool check() {
    auto duration_since_epoch = clk_t::now().time_since_epoch();
    long curr_time_slice =
        std::chrono::duration_cast<std::chrono::seconds>(duration_since_epoch).count() /
        time_slice_; // integer division!

    if (curr_time_slice != last_time_slice_) {
      last_time_slice_ = curr_time_slice;
      count_           = 0;
    }
    ++count_;
    return (count_ <= n_);
  }

private:
  unsigned n_;
  long     time_slice_;
  long     last_time_slice_ = 0;
  unsigned count_           = 0;
  ;
};

acquire metodu
Şöyle yaparız.
while (true) {
  rateLimiter.acquire();
  ...
}
create metodu - SmoothBursty
İmzası şöyle
static RateLimiter create(double permitsPerSecond)
Metod altta şöyledir.
static RateLimiter create(SleepingStopwatch stopwatch, double permitsPerSecond) {

  RateLimiter rateLimiter = new SmoothBursty(stopwatch, 1.0 /* maxBurstSeconds */); 
  rateLimiter.setRate(permitsPerSecond);
  return rateLimiter;
}
Örnek
Saniyede bir oran için şöyle yaparız.
RateLimiter msgLimiter  = RateLimiter.create(1);
Örnek
Elimizde şöyle bir kod olsun. RateLimiter dolu başlar. Bekleme aralıkları sabit olduğu için hep aynı süre bekleriz
RateLimiter rt = new RateLimiter.create(2);
System.out.println(rt.acquire()); System.out.println(rt.acquire()); System.out.println(rt.acquire()); System.out.println(rt.acquire()); System.out.println(rt.acquire()); System.out.println(rt.acquire());
Çıktı olarak şunu alırız
0.0
0.498957
0.497851
0.499391
0.499364
Örnek
Elimizde şöyle bir kod olsun. Saniyede 2 istek işler.
RateLimiter rl = RateLimiter.create(2);
System.out.println(rl.getRate());
System.out.println(rl.tryAcquire());
System.out.println(rl.tryAcquire());
System.out.println(rl.tryAcquire());
Çıktı olarak şunu alırız. İkinci istek false döner çünkü istekleri eşit dağıtmaya çalışır.
2.0
true
false
false
create metodu - SmoothWarmingUp
İmzası şöyle
static RateLimiter create(double permitsPerSecond, long warmupPeriod, TimeUnit unit)
Metod altta şöyledir.
static RateLimiter create(SleepingStopwatch stopwatch, double permitsPerSecond,
long warmupPeriod, TimeUnit unit, double coldFactor) {

  RateLimiter rateLimiter = new SmoothWarmingUp(stopwatch, warmupPeriod, unit,
coldFactor);
  rateLimiter.setRate(permitsPerSecond);
  return rateLimiter;
}
Açıklaması şöyle
The RateLimiterSmoothWarmingUp method has a warm-up period after the startup. It gradually increases the distribution rate to the configured value.

For example, you can use the following snippet to create a ratelimiter with an average token creation rate of 2 tokens/s, and a warm-up period of 3 seconds. The token bucket does not create a token every 0.5 seconds immediately after startup, because a warm-up period of 3 seconds has been set. Instead, the system gradually increases the token creation rate to the pre-set value within 3 seconds and then creates tokens at a fixed rate. This feature is suitable for scenarios where the system needs some time to warm up after startup.

RateLimiter r = RateLimiter.create(2, 3, TimeUnit.SECONDS);
Örnek
Elimizde şöyle bir kod olsun. RateLimiter dolu başlar. 4 saniye boyunca yavaştır yani ısınır. Isınması gittikçe daha hızlanarak sürer. 4 saniye sonunda normal hızında yani saniyede 2 tane token üretmeye başlar.
RateLimiter rt = new RateLimiter.create(2,4, TimeUnit.SECONDS);
System.out.println(rt.acquire()); System.out.println(rt.acquire()); System.out.println(rt.acquire()); System.out.println(rt.acquire()); System.out.println(rt.acquire()); System.out.println(rt.acquire());
Çıktı olarak şunu alırız
0.0
1.3743
1.123576
0.874151
0.624409 
0.50001
tryAcquire metodu
Şöyle yaparız.
while (true) {
  
  if (rateLimiter.tryAcquire()) {
    ...
  }
}

12 Haziran 2019 Çarşamba

InetAddresses Sınıfı

Giriş
Bu sınıf JDK'daki InetAddress sınıfını tamamlıyor ile IP adresleri ile çalışmayı daha da kolaylaştırıyor.

isInetAddress metodu
Verilen parametrenin nokta ile ayrılmış IP string adresi olup olmadığı kontrol eder.


HashMultimap Sınıfı

create metodu
HashMultimap nesnesi döner.
Örnek
HashMultimap nesnesi MultipMap arayüzünden kalıttığı için şöyle yaparız.
Multimap<String, String> m = HashMultimap.create();
Örnek
HashMultimap nesnesi SetMultipMap arayüzünden kalıttığı için şöyle yaparız..
SetMultimap<Long, SomeClass> encounters = new Hashmultimap.create();
Örnek
Eğer thread safe olsun istesek şöyle yaparız.
Multimap<String, String> m = HashMultimap.create();
Multimap<String, String> n = Multimaps.synchronizedMultimap(m);
asMap metodu
Örnek
Bir key nesnesini tamemen silmek için şöyle yaparız.
Collection<Foo> values = multimap.asMap().remove(key);
Örnek
key + value collection olarak dolaşmak için şöyle yaparız.
for (Map.Entry<String, Collection<SomeClassObject>> entry : multimap.asMap().entrySet()) {
  String key = entry.getKey();
  Set<SomeClassObject> valuesForKey = multimap.get(key);
   // do whatever
}
Örnek
Sadece value collection olarak dolaşmak için şöyle yaparız.
for (Collection collection : multimap.asMap().values()) { ... }
containsKey metodu - key
boolean döner. Şöyle yaparız.
System.out.println("contains key 1? " + lmm.containsKey(1));
entries metodu
Şöyle yaparız.
for (Map.Entry entry : multimap.entries()) { ... }
get metodu - key
Metodu imzası şöyle
@Override
public Set<V> get(@Nullable K key);
Ata metodunu çağırır. Ata metodun imzası şöyle.
Collection<V>   get(K key) 
Ata metodun içi şöyle. Eğer key yoksa bile boş bir collection döner. Bu collection Set'e cast edilir.
/**
 * {@inheritDoc}
 *
 * <p>The returned collection is not serializable.
 */
@Override
public Collection<V> get(@Nullable K key) {
  Collection<V> collection = map.get(key);
  if (collection == null) {
    collection = createCollection(key);
  }
  return wrapCollection(key, collection);
}
keys metodu
key nesnesi çoklu değer taşıyorsa birden fazla karşımıza çıkar.  Açıklaması şöyle.
all keys (a key that maps to multiple values coming up multiple times in the iteration):
Örnek
Şöyle yaparız.
for (Object key : multimap.keys()) { ... }
keySet metodu
key nesnelerini tek bir kere dolaşmak içindir.

Örnek
Şöyle yaparız.
for (Object key : multimap.keySet()) { ... }
Örnek
şöyle yaparız.
for (String key : multimap.keySet()) {
  Collection<SomeClassObject> values = multimap.get(key);
  //Do whatever with all the values for Key key...
}
Örnek
Şöyle yaparız.
Set keySet = listmultimap.keySet();
Iterator keyIterator = keySet.iterator();
while (keyIterator.hasNext() ) {
  String key = (String) keyIterator.next();
  List values = listmultimap.get( key );

}
put metodu - key + value
Şöyle yaparız.
// A set multimap.
SetMultimap<Integer, Integer> smm = HashMultimap.<Integer, Integer> create();
smm.put(1, 2);
putAll metodu
Elimizde şöyle bir kod olsun.
Map<T, K> map1 = ...;
Şöyle yaparız.
multimap.putAll(Multimaps.forMap(map1));
remove metodu - key + value
Şöyle yaparız. Key ile ilişkili value nesnesini siler. En son value da silinince key nesnesi de silinir.
// A set multimap.
SetMultimap<Integer, Integer> smm = HashMultimap.<Integer, Integer> create();
smm.put(1, 2);
smm.remove(1, 2);
// Value of key 1 in HashMultimap: []
System.out.println("Contains key 1 in HashMultimap: " + smm.containsKey(1));