28 Mayıs 2021 Cuma

RxJava AsyncSubject Sınıfı

Giriş
Açıklaması şöyle
AsyncSubject emits only the last value of the Observable and this only happens after the Observable completes.
Örnek 
Elimizde şöyle bir kod olsun
AsyncSubject<Integer> pSubject = AsyncSubject.create();
pSubject.onNext(0);

pSubject.subscribe(it -> System.out.println("Observer 1 onNext: " + it),
                  (Throwable error) -> { }, () -> System.out.println("Observer 1 onComplete"),
                  on1 -> System.out.println("Observer 1 onSubscribe"));

pSubject.onNext(1);
pSubject.onNext(2);


pSubject.subscribe(it -> System.out.println("Observer 2 onNext: " + it),
                  (Throwable error) -> { }, () -> System.out.println("Observer 2 onComplete"),
                  on1 -> System.out.println("Observer 2 onSubscribe"));

pSubject.onNext(3);
pSubject.onNext(4);

/* This is very important in AsyncSubject  */
pSubject.onComplete();
Çıktı olarak şunu alırız
Observer 1 onSubscribe
Observer 2 onSubscribe
Observer 1 onNext: 4
Observer 1 onComplete
Observer 2 onNext: 4
Observer 2 onComplete

RxJava UnicastSubject Sınıfı

Giriş
Açıklaması şöyle
UnicastSubject allows only a single subscriber and it emits all the items regardless of the time of subscription.
Örnek
Şöyle yaparız
Observable<Integer> observable = Observable.range(1, 5)
                .subscribeOn(Schedulers.io());


UnicastSubject<Integer> pSubject = UnicastSubject.create();
observable.subscribe(pSubject);


pSubject.subscribe(it -> System.out.println("onNext: " + it));
Çıktı olarak şunu alırız
onNext: 1
onNext: 2
onNext: 3
onNext: 4
onNext: 5

RxJava BehaviorSubject Sınıfı - En Son Yayınlanan Nesneyi Yeni Aboneye Gönderir

Giriş
Açıklaması şöyle
BehaviorSubject emits the most recent item at the time of their subscription and all items after that. 
Örnek 
Elimizde şöyle bir kod olsun
BehaviorSubject<Integer> pSubject = BehaviorSubject.create();
pSubject.onNext(0);


pSubject.subscribe(it -> System.out.println("Observer 1 onNext: " + it),
                  (Throwable error) -> { }, () -> {},
                  on1 -> System.out.println("Observer 1 onSubscribe"));

pSubject.onNext(1);
pSubject.onNext(2);


pSubject.subscribe(it -> System.out.println("Observer 2 onNext: " + it),
                  (Throwable error) -> { }, () -> {},
                  on1 -> System.out.println("Observer 2 onSubscribe"));

pSubject.onNext(3);
pSubject.onNext(4);
Çıktı olarak şunu alırız. 2 numaralı katılımcı abone olduğunda 2 değeri zaten yayınlanmıştı, ancak yine de duyabilir.
Observer 1 onSubscribe
Observer 1 onNext: 0
Observer 1 onNext: 1
Observer 1 onNext: 2
Observer 2 onSubscribe
Observer 2 onNext: 2
Observer 1 onNext: 3
Observer 2 onNext: 3
Observer 1 onNext: 4
Observer 2 onNext: 4

RxJava ReplaySubject Sınıfı

Giriş
Açıklaması şöyle
ReplaySubject emits all the items of the Observable, regardless of when the subscriber subscribes.
Örnek
Elimizde şöyle bir kod olsun
ReplaySubject<Integer> pSubject = ReplaySubject.create();
pSubject.onNext(0);


pSubject.subscribe(it -> System.out.println("Observer 1 onNext: " + it),
                  (Throwable error) -> { }, () -> {},
                  on1 -> System.out.println("Observer 1 onSubscribe"));

pSubject.onNext(1);
pSubject.onNext(2);


pSubject.subscribe(it -> System.out.println("Observer 2 onNext: " + it),
                  (Throwable error) -> { }, () -> {},
                  on1 -> System.out.println("Observer 2 onSubscribe"));

pSubject.onNext(3);
pSubject.onNext(4);
Çıktı olarak şunu alırız. Aslında bir anlamda Cold Observale'ın tüm çıktısı kaydediliyor ve kaydedilen şey tekrar en baştan oynatılıyor.
Observer 1 onSubscribe
Observer 1 onNext: 0
Observer 1 onNext: 1
Observer 1 onNext: 2
Observer 2 onSubscribe
Observer 2 onNext: 0
Observer 2 onNext: 1
Observer 2 onNext: 2
Observer 1 onNext: 3
Observer 2 onNext: 3
Observer 1 onNext: 4
Observer 2 onNext: 4
Yani ReplaySubject pahalı işlemleri bir şekilde cache'lemek için kullanılabilir
Örnek
Elimizde şöyle bir kod olsun
Observable<Integer> observable = Observable.range(1, 5)
                .subscribeOn(Schedulers.io());

//Record everyting
ReplaySubject<Integer> subject = ReplaySubject.create();
observable.subscribe(subject);

//Replay everything
subject.subscribe(s -> System.out.println("subscriber one: " + s));

//Replay everything
subject.subscribe(s -> System.out.println("subscriber two: " + s));
Çıktı olarak şunu alırız
subscriber one: 1
subscriber one: 2
subscriber one: 3
subscriber one: 4
subscriber one: 5
subscriber two: 1
subscriber two: 2
subscriber two: 3
subscriber two: 4
subscriber two: 5

27 Mayıs 2021 Perşembe

RxJava Subjects

Giriş
Açıklaması şöyle
A Subject extends an Observable and implements Observer at the same time. It acts as an Observable to clients and registers to multiple events taking place in the app. It acts as an Observer by broadcasting the event to multiple subscribers.
Peki Subject neden Observable'a abone olup tekrar Observable hale getiriyor. Buradaki amaçlardan bir tanesi şu
Subjects are considered as HOT Observables.

A HOT Observable, such as Subjects, emits items only once regardless of number of subscribers and its subscribers receive items only from the point of their subscription. Subjects convert cold observable into hot observable.
Bir çok Subject gerçekleştirimi var. Bunlar şöyle

25 Mayıs 2021 Salı

Arrays.parallelPrefix metodu

Giriş
Açıklaması şöyle. Yani her elemana bir önceki elemana uygulanmış metot çıktısını uygular
Cumulates, in parallel, each element of the given array in place, using the supplied function. For example if the array initially holds [2, 1, 0, 3] and the operation performs addition, then upon return the array holds [2, 3, 3, 6]. Parallel prefix computation is usually more efficient than sequential loops for large arrays.
Örnek
Şöyle yaparız
int[] numbers = {1, 2, 3, 4, 5};
Arrays.parallelPrefix(numbers, (x, y) -> x * y); // 2nd arg is lambda 

// The original array is now updated
System.out.println(Arrays.toString(numbers));

// Output: {1, 2, 6, 24, 120}
Örnek
Şöyle yaparız
int[] nums = {1, 1, 1, 2, 3};
Arrays.parallelPrefix(nums,Integer::sum);
System.out.println(Arrays.toString(nums));

//[1, 2, 3, 5, 8]

int[] nums = {1, 2, 3, 4, 5};
Arrays.parallelPrefix(nums, (i,j) -> i*j);
System.out.println(Arrays.toString(nums));

//[1, 2, 6, 24, 120]

19 Mayıs 2021 Çarşamba

BitStream

Giriş
Sınıf şöyle olsun. Byte'lar yazacağımız için 8 tane mask yeterli.
public class BitStream {
  protected byte[] data;
  protected byte[] sizeInBytes;
  protected int bitPosition;
  protected int bytePosition;

  static final int BYTE_LENGTH = 8;
  static final int DEFAULT_SIZE = 16;
  static final int GROW_SIZE = 16;
  static int[] MASKS = {
    0,        //0
    0x1,      //1
    0x3,      //2
    0x7,      //3
    0xf,      //4
    0x1f,     //5
    0x3f,     //6
    0x7f,     //7
    0xff,     //8
  }
  ...
}
Constructor metodlar şöyle
//For writing public BitStream { data = new byte[DEFAULT_SIZE]; sizeInBytes = data.length; } //For writing public BitStream(int capacity) { data = new byte[capacity]; sizeInBytes = data.length; } //For reading public BitStream(byte[] data { this.data = data; sizeInBytes = data.length; }
Bazı yardımcı metodlar şöyle
public void flipForReading(){
  data = toByteArray();
  bitPosition = 0;
  bytePosition = 0;  
}

public void growCapacity() {
  data = Arrays.copyOf(data,data.length + GROW_SIZE);
}
//Compelete or partial readable bytes after write operation
public int getReadableBytes() {
  if (bytePosition == 0 && bitPosition == 0) {
    return 0;
  }
  return bytePosition + 1;
}

public byte[] toByteArray() {
  int length = getReadableBytes();
  return Arrays.copyOf(data,length);
}
readNBits metodu
Burada en fazla 32 bit okunabilir. Bit shift işlemleri integer olarak yapılıyor ancak sonuç unsigned olsun diye long olarak döndürülüyor.
- //1 ile işaretli yerde mask bitPosition sayısı kadar kaydırılır. Böylece doğru mask elde edilir. Buffer'dan istenilen bit sayısı okunduktan sonra elde edilen değer tekrar sağa kaydırılır.

- //2 ile işaretli yerde okunan değer toplam okunan bit sayısı kadar kaydırılır ve sonuca dahil edilir.
public long readNBits (int numBits) { if (numBits > 32) { throw new IllegalArgumentException(); } int result = 0; int bitsReadSoFar = 0; while (numBits > 0) { int bitsToRead = numBits; //It is ok to pass the buffer boundary if (bitPosition == BYTE_LENGTH) { gotoNextByte(); } if (numBits + bitPosition) > BYTE_LENGTH) { bitsToRead = BYTE_LENGTH - bitPosition; } numberOfBits -= bitsToRead; //1 int buf = ((MASKS [bitsToRead] << bitPosition) & data [bytePosition]) >> bitPosition; bitPosition += bitsToRead; //2 result |= (buf << bitsReadSoFar); bitsReadSoFar += bitsToRead; } //while return Integer.toUnsignedLong(result); }
gotoNextByte şöyle
protected void gotoNextByte() {
  ++bytePosition;
  bitPosition = 0;
}
writeNBits metodu
Şöyle
public void writeNBits(long value, int numBits) {
  if (numbits > 32) {
    throw new IllegalArgumentException();
  }
  while(numBits > 0) {
    int bitsToWrite = numBits;
    if (bitPosition == BYTE_LENGTH) {
      gotoNextByte();
    }
    if ((numBits + bitPosition) > BYTE_LENGTH) {
      bitToWrite = BYTE_LENGTH - bitPosition;
    }

    numBits -= bitsToWrite;
    data[bytePosition] &= (byte) ~(MASKS[bitsToWrite] << bitPosition);
    data[bytePosition] |= (byte) ((value & MASKS[bitsToWrite]) << bitPosition);

    bitPosition += bitsToWrite;

    value = (value >> bitsToWrite);
  }
}
Elimizde bu iki metod olduktan sonra diğer tipleri yazıp okumak kolay. Şöyle yaparız
public boolean readBoolean() {
  int data = (int) readNBits (1);
  return data == 1;
}

public void writeBoolean(boolean value) {
  int data = value ? 1 : 0;
  writeNBits(data,1);
}

public float readFloat() {
  int intBits = (int) readNBits(32);
  return Float.intBitsToFloat(intBits);
}

public void writeFloat(float value) {
  int intBits = Float.floatToRawIntBits(value);
  writeNBits(intBits,32);
}


17 Mayıs 2021 Pazartesi

RxJava Observable.debounce metodu

Giriş
Eğer event'ler çok hızlı geliyorsa, seyreltmek için kullanılır.

Örnek
Şöyle yaparız
inputObservable.debounce(1, TimeUnit.SECONDS)
.subscribe(new Action1<String>() { @Override public void call(String s) { ... } });

RxJava Observable.zip metodu

Giriş
İşleri paralel çalıştırır.
Örnek
Şöyle yaparız
Observable.zip(api.getUserDetails2(userId), api.getUserPhoto2(userId),
(details, photo) -> Pair.of(details, photo)) .subscribe(p -> { // Do your task. });

16 Mayıs 2021 Pazar

Netty ReplayingDecoder Sınıfı - ByteBuf Nesnesini Java Nesnesine Çevirir

Giriş
Açıklaması şöyle.
It uses an implementation of ByteBuf which throws an exception when there is not enough data in the buffer for the reading operation.

When the exception is caught the buffer is rewound to the beginning and the decoder waits for a new portion of data. Decoding stops when the out list is not empty after decode execution.
ByteToMessageDecoder sınıfında kalıtır.

Örnek
Şöyle yaparız
public class RequestDecoder extends ReplayingDecoder<RequestData> {

  private final Charset charset = Charset.forName("UTF-8");

  @Override
  protected void decode(ChannelHandlerContext ctx, 
    ByteBuf in, List<Object> out) throws Exception {
 
    RequestData data = new RequestData();
    data.setIntValue(in.readInt());
    int strLen = in.readInt();
    data.setStringValue(
      in.readCharSequence(strLen, charset).toString());
    out.add(data);
  }
}

7 Mayıs 2021 Cuma

hprof Profiling

Giriş
Söz dizimi şöyle
java -agentlib:hprof[=options] ToBeProfiledClass
java -Xrunprof[:options] ToBeProfiledClass
javac -J-agentlib:hprof[=options] ToBeProfiledClass
Options için açıklama şöyle
Option Name and Value  Description                    Default
---------------------  -----------                    -------
heap=dump|sites|all    heap profiling                 all
cpu=samples|times|old  CPU usage                      off
monitor=y|n            monitor contention             n
format=a|b             text(txt) or binary output     a
file=<file>            write data to file             java.hprof[.txt]
net=<host>:<port>      send data over a socket        off
depth=<size>           stack trace depth              4
interval=<ms>          sample interval in ms          10
cutoff=<value>         output cutoff point            0.0001
lineno=y|n             line number in traces?         y
thread=y|n             thread in traces?              n
doe=y|n                dump on exit?                  y
msa=y|n                Solaris micro state accounting n
force=y|n              force output to <file>         y
verbose=y|n            print messages about dumps     y
cpu seçeneği
Örnek - samples
Şöyle yaparız
java -agentlib:hprof=cpu=samples,interval=20,depth=20 -jar target.jar
Örnek - samples
Şöyle yaparız
java -agentlib:hprof=cpu=samples,interval=20,depth=3 Hello
Açıklaması şöyle
The CPU consumption information is sampled every 20 milliseconds, the stack depth is 3, and the name of the generated profile file is java.hprof.txt, which is in the current directory.
Örnek - times
Şöyle yaparız
javac -J-agentlib:hprof=cpu=times Hello.java
Açıklaması şöyle
An example of CPU Usage Times Profiling (cpu=times), which can obtain more fine-grained CPU consumption information than CPU Usage Sampling Profile, and can be detailed to the beginning and end of each method call. Its implementation uses bytecode injection Technology (BCI):
heap seçeneği
Örnek - sites
Şöyle yaparız
javac -J-agentlib:hprof=heap=sites Hello.java
Açıklaması şöyle
Example of Heap Allocation Profiling (heap=sites):
Açıklaması şöyle
Although the -Xrunprof:heap=sites parameter can be added to the JVM startup parameters to generate the CPU/Heap Profile file, but it has a great impact on the performance of the JVM, and it is not recommended to use it in an online server environment.
Örnek - dump
Şöyle yaparız
javac -J-agentlib:hprof=heap=dump Hello.java
Açıklaması şöyle
An example of Heap Dump(heap=dump), which can generate more detailed Heap Dump information than the above Heap Allocation Profiling:





4 Mayıs 2021 Salı

CompletableFuture.handle metodu - State Normal veya Hatalı Bitse de Çağrılır

Giriş
Açıklaması şöyle
If you need to recover from an exception (to replace the exception with some default value), you should use the handle and exceptionally methods. A BiFunction argument of the handle method is called when the previous stage completes normally or exceptionally. A Function argument of the exceptionally method is called when the previous stage completes exceptionally. In both cases, an exception is not propagated to the next stage.
Açıklaması şöyle
returns a new CompletionStage that upon normal or exceptional completion transforms the result or exception of this stage and returns the new result
Açıklaması şöyle
This method takes a BiFunction as an argument:
- Result and Exception are parameters ( one is null )
- This method will always be executed regardless of whether an exception occurs or not allowing you to recover or throw an exception downstream
Bir önceki CompletionStage bitince çağrılır. Eğer exception olursa birinci parametre null, ikinci parametre exception'dır. 
Örnek
Şöyle yaparız.
public static F.Promise<Void> performAllItemsBackup(Stream<Item> stream) {
  return F.Promise.pure(stream).flatMap(items -> {
    ExecutorService pool = Executors.newFixedThreadPool(3);
    try {
      return CompletableFuture.allOf(
        items.map(CompletableFuture::completedFuture)
             .map(f -> f.thenAcceptAsync(performSingleItemBackup, pool))
             .toArray(CompletableFuture<?>[]::new))
             .handle((v, e) -> e!=null? F.Promise.<Void>throwing(e): F.Promise.pure(v))
             .join();
    } finally {
      pool.shutdown();
    }
  });
}