27 Temmuz 2022 Çarşamba

Happens-Before İlişkisi

Giriş 
Açıklaması şöyle
JVM can change the order of the instructions which won't make any significant changes in the program. 
Happens-Before Nedir
Açıklaması şöyle. Bir açıklama da burada.
If between two threads, we installed the happens-before relation, then the second (ending thread) will see all changes that happened in the first thread. Therefore, the second thread execution will be similar to a single thread application.
Happens-Before İlişkisi Nasıl Kurulur
1. volatile kelimesi kullanılır
2. final kelimesi kullanılır
2. Synchronized Monitor kullanılır
3. Thread start() ve join() çağrılarında otomatik kurulur
Yani başlayan thread, parent thread içindeki değişiklikleri görür. Child thread bitince de parent thread join() ile beklediği için, child thread tarafından yapılan değişiklikleri görür

final Anahtar Kelimesi
Örnek - Yanlış Kod
class Example {
final int foo; Example() { foo = 42; } static Example instance; static void threadOne() { instance = new Example(); // Look at two steps below, they depict `new Example()` //instance = <allocate space in Heap: Example>; // instance.<init>(); } static void threadTwo() { if (instance != null) { assert instance.foo == 42; } } }
Açıklaması şöyle
1. First thread starts initialization. First step of initialization happens
2. Second thread checks the object for being not null . Sees that it is not -> grabs it. But it isn’t fully initialized yet. => Error prone as second step of initialization hasn’t ended in the first thread.

=> we have only partial happens-before working here as we didn’t get the full object.

Solution — use final keyword.

final field makes variable freeze — JVM isn’t allowed to publish an instance to another thread before setting the field to the value(s) it receives in the constructor.
Synchronized Monitor
Örnek
Açıklaması şöyle
... when the first thread updates the value and releases the lock, then in the second thread when the lock is acquired, the value also gets updated due to the happened-before relation. This rule applied to all locks from java.util.concurrent that use a Java monitor under the hood.  
Şöyle yaparız
private static final Object Lock = new Object();

public class Foo {
  //Volatile gerekli değil ancak kullanmakta fayda var
  volatile int x;
  volatile in y;
}

final Foo foo = new Foo ();
Thread t1 = new Thread(()-> {
  synchronized(Lock) {
    foo.x = 1;
    foo.y = 1;
    Lock.notifyAll();
  }
});

Thread t2 = new Thread(()-> {
  synchronized(Lock) {
    while(foo.x == 0) {
      try {
        Lock.wait();
      } catch (InterruptedException ignored) {}
    }  
  }
  System.out.println(foo.y + foo.x);
});

t1.start();
t2.start();
Parent Thread
Örnek
Şöyle yaparız
lass ThreadStart {

  int foo = 0;
  
  void threadStart() {
    foo = 40;
    new Thread() {
      @Override
      public void run() {
         assert foo == 40;
      }
    }.start();
  }
}
Açıklaması şöyle
Thread 1 starts thread 2 -> thread 2 is guaranteed to see all the data from thread 1
Thread 1 joins thread 2 -> thread 1 sees all data from thread 2 (of the joined thread)



26 Temmuz 2022 Salı

Redisson API

Giriş
Redisson için açıklama şöyle
Redisson adopts the nety framework based on NIO, which can not only be used as the underlying driver client of Redis, but also can send redis commands in synchronous, asynchronous, asynchronous stream or pipeline forms, execute and process Lua scripts, and process the returned results.
Maven
Şu satırı dahil ederiz
<groupId>org.redisson</groupId>
  <artifactId>redisson</artifactId>
  <version>3.16.2</version>
</dependency>
Gradle
Şu satırı dahil ederiz
dependencies {
    implementation 'org.redisson:redisson:3.20.1'
}
RedissonClient Sınıfı
Örnek
Şöyle yaparız
import org.redisson.Redisson
import org.redisson.api.RedissonClient
import org.redisson.config.Config

fun main() {
  // Create Redisson configuration
  val config = Config()
  config.useSingleServer().address = "redis://127.0.0.1:6379"

  // Initialize Redisson client
  val redisson: RedissonClient = Redisson.create(config)

  // Distributed Map Example
  val users = redisson.getMap<String, String>("users")
  users["john"] = "John Doe"
  users["jane"] = "Jane Doe"
  println("User Map: $users")

  // Distributed Queue Example
  val tasks = redisson.getQueue<String>("tasks")
  tasks.offer("Task 1")
  tasks.offer("Task 2")
  tasks.offer("Task 3")
  println("Queue Size: ${tasks.size}")

  // Clean up
  redisson.shutdown()
}
RBucket Sınıfı
Örnek
Şöyle yaparız
//key value get and set
RBucket<String> nameRBucket =  redisson.getBucket("username");
nameRBucket.set("lance", 60, TimeUnit.SECONDS);
redisson.getBucket("username").get();
RMap Sınıfı
Örnek
Şöyle yaparız
//operate hashes
RMap<String, String> userMap = redisson.getMap("user");
userMap.put("id", "1");
userMap.put("name", "lance");
userMap.put("age", "30");

userMap.expire(60, TimeUnit.SECONDS);
redisson.getMap("user").get("name");

//operate lists
RList<String> usernames = redisson.getList("usernames");
users.add("lance");

studentRList.expire(60, TimeUnit.SECONDS);
redisson.getList("usernames").get(0);
RList Sınıfı
Örnek
Şöyle yaparız
//operate lists
RList<String> usernames = redisson.getList("usernames");
users.add("lance");

studentRList.expire(60, TimeUnit.SECONDS);
redisson.getList("usernames").get(0);
RStream Sınıfı
Örnek
Bu Kotlin kodu. Şöyle yaparız
@OptIn(DelicateCoroutinesApi::class)
suspend fun redisStreamWithRedisson() {
  // Create Redisson configuration
  val config = Config()
  config.useSingleServer().address = "redis://localhost:6379"

  // Initialize Redisson client
  val redisson: RedissonClient = Redisson.create(config)

  // Creating a Redis Stream
  val consumerGroup = "my_group"
  val streamName = "my_stream"
  val stream = redisson.getStream<String, String>(streamName)

  // Adding messages to a Redis Stream
  val job = GlobalScope.launch {
    for (i in 1..10) {
      val id = stream.add("key", "message $i", 10_000, true)
      println("Added message $i with id $id to stream")
    }
  }

  // Waiting for the producer to finish
  job.join()

  // Consuming messages from a Redis Stream
  val consumerId = "my_consumer"
  stream.createConsumer(consumerGroup, consumerId)
  val jobs = mutableListOf<Job>()
  repeat(2) {
    jobs.add(GlobalScope.launch {
      while (true) {
        val messages = stream.readGroup(consumerGroup, consumerId, 5,
                  StreamMessageId.NEVER_DELIVERED)
        for (message in messages) {
          val messageId = message.key
          println("Job $it - Received $message")
          stream.ack(consumerGroup, messageId)
        }
      }
    })
  }

  // Waiting for the consumers to finish
  jobs.joinAll()

  // Clean up
  redisson.shutdown()
}



20 Temmuz 2022 Çarşamba

IntelliJ Idea Java Compiler Ekranı

Giriş
Bu ekranın yolu şöyle
Preferences -> Build, Execution, Deployment -> Compiler -> Java Compiler
--enable-preview Hatası Alıyorsak
"Use --release’" seçeneği kapatılır ve "Additional command line parameters" altına "--enable ..." seçeneği eklenir. Şeklen şöyle. Bu sadece derlemek içindir. Çalıştırmak için halen "Run/Debug Configurations" altında başka seçenekleri vermek lazım

Per-module bytecode version
Eğer bazı modüller projeden farklı bytecode üretecekse bu ekranda gösterilir. Şeklen şöyle. Burada "project bytecode version" Java 8 ama bazı modüller "Java 17" kullanıyor






Epsilon Garbage Collector - Java 11 İle Geliyor

Giriş
Açıklaması şöyle
Epsilon only allocates memory and does not release it like JVM GC. Using this new garbage collector is really helpful in a test environment as no memory clearance overhead. Therefore, it gives an accurate performance test result. There is a note that Epsilon is good only for test environments because it will lead to OOM (OutOfMemory) in production and crash the Java application.
Açıklaması şöyle
Java 11 introduced a no-operations(No-Op) garbage collector called Epsilon. This is an experimental feature. It is called a No-Op garbage collector because it will allocate memory but will never collect any garbage. We can use it for simulating Out-Of-Memory errors. The following are some of its use cases.

- Performance testing
- Memory pressure testing
- VM interface testing and
- Extremely short-lived jobs
- Last-drop latency and throughput improvements
Örnek
Şöyle yaparız
-XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC



 

13 Temmuz 2022 Çarşamba

OptionalDouble Sınıfı

Giriş
Açıklaması şöyle
An OptionalDouble object is one that can potentially contain a double number. Methods in the class can be used to work with the double value present in the object, or specify that there is no double contained at all.
getAsDouble metodu
Açıklaması şöyle
getAsDouble() is one of these methods, and it essentially returns the double value if there is one present. Otherwise, NoSuchElementException is thrown.
Örnek
Şöyle yaparız
OptionalDouble num = OptionalDouble.of(15.0);
System.out.println(num.getAsDouble());// Output: 15.0
of metodu
Örnek
Şöyle yaparız
OptionalDouble val = OptionalDouble.empty();
OptionalDouble val2 = OptionalDouble.of(15.0);

System.out.println("val2 >>");
System.out.println("A value is present: " + val2.isPresent());
System.out.println("Double contained: " + val2.getAsDouble());
System.out.println("Equal to 15: " + val2.equals(15.0));
System.out.println();
System.out.println("val >>");
System.out.println("A value is present: " + val.isPresent());
System.out.println("Double contained: " + val.getAsDouble());
/*
Output:
val2 >>
A value is present: true
Double contained: 15.0
Equal to 15: false
val >>
A value is present: false
NoSuchElementException
*/

CLASSPATH

Giriş
Açıklaması şöyle.
Classpath in Java is the path to a directory or list of directories that is used by ClassLoaders to find and load class in Java program. Classpath can be specified using CLASSPATH environment variable which is case insensitive, -cp or -classpath command line option or Class-Path attribute in manifest.mf file inside JAR file in Java. From below you can find out some important points about java CLASSPATH

1. Classpath in Java is an environment variable used by Java Virtual machine to locate or find class files in Java during class loading.

2. You can override value of Classpath in Java defined by environment variable CLASSPATH by providing JVM command line option –cp or –classpath while running your application.

3. If two classes with same name exist in Java Classpath then the class which comes earlier in Classpath will be picked by Java Virtual Machine.

4. By default CLASSPATH in Java points to current directory denoted by ”.” and it will look for any class only in current directory.

5. When you use the -jar command line option to run your program as an executable JAR, then the Java CLASSPATH environment variable will be ignored, and also the -cp and -classpath switches will be ignored and In this case you can set your java classpath in the META-INF/MANIFEST.MF file by using the Class-Path attribute.

6. In Unix of Linux Java Classpath contains names of directory with colon ”:” separated , On Windows Java Classpath will be semi colon ”;” separated while if you defined java classpath in Manifest file those will be space separated.

7. You can check value of classpath in java inside your application by looking at following system property “java.class.path” System.getProperty(“java.class.path”)
Yani
1. CLASSPATH ortamı değişkeni tanımlanır
2. JVM'i çaşıltırırken -cp seçeneği belirtilir. -cp seçeneği CLASSPATH ortamı değişkenini ezer
3. Executable jar için bu iki seçenek kullanılmaz. Sadece Manifest dosyasında "Class-Path" alanı kullanılır

1. CLATTPATH Ortam Değişkeni
Çalıştırılan uygulama CLASSPATH değişkeninde tanımlı jar'ları bulur

Örnek - Dizin
Windows'ta şöyledir.
C:\...\jdk1.8.0_77\bin;C:\...\jre1.8.0_77\bin
Örnek - Jar Dosyası
Şöyle yaparız
#Windows
set CLASSPATH=C:\a\Application.jar;C:\b\Application.jar

#Linux
export CLASSPATH=/a/Application.jar:/b/Application.jar

#MAC
export CLASSPATH=${CLASSPATH}:/a/Application.jar:/b/Application.jar
java.
2. JVM - cp seçeneği
Açıklaması şöyle.
$ java -help
    …
    -cp <class search path of directories and zip/jar files>
    -classpath <class search path of directories and zip/jar files>
                  A : separated list of directories, JAR archives,
                  and ZIP archives to search for class files.
Örnek - Dizin
Şöyle yaparız.
bash$ java -classpath path/to/jars/directory MyMainClass
Örnek - Dizin
Şöyle yaparız. bind isimli dizin kullanılır
"%JAVA_HOME%\jre\bin\java.exe" -classpath bind MyMainClass
Örnek - Birden fazla dizin
Windows'ta tek tırnak ile şöyle yaparız. Dizinler ; karakteri ile ayrılır
java -verbose -classpath '../lib;.' bt_sim <args>
Linux'ta dizinler : karakteri ile ayrılır.

Bu seçeneği kullanmak yerine CLASSPATH ortam değişkenini kullanmak daha iyi.
bash$ export CLASSPATH="path/to/jars/directory1:path/tojars/directory2"
bash$ javac MyMainClass.java
Örnek - wildcard
Açıklaması şöyle.
Class path entries can contain the basename wildcard character *, which is considered equivalent to specifying a list of all the files in the directory with the extension .jar or .JAR. For example, the class path entry foo/* specifies all JAR files in the directory named foo. A classpath entry consisting simply of * expands to a list of all the jar files in the current directory.
Bir dizindeki tüm jar'ları dahil etmek için şöyle yaparız.
java -cp /home/acelya/*: MyMainClass
Class Path Jar Sırası
Açıklaması şöyle. ClassLoader ClassPath'i tararken ilk bulduğu jar'ı kullanır
If I were to invoke my program with

java -cp A.jar:B.jar ExampleMain

the output is: Hello, A!

If I reverse the classpath like so

java -cp B.jar:A.jar ExampleMain

the output is: Hello, B!

4 Temmuz 2022 Pazartesi

SoftReference Nesnesi

Giriş
Açıklaması şöyle. Yani WeakReference'tan biraz daha katıdır ve OutOfMemory oluncaya kadar belleği bırakmamaya çalışırlar
Soft References behave very similarly to the weak ones with the difference that they are not that eager to let the object to be collected. They behave like strong references until the memory runs out. If the JVM starts reaching its upper ram limits it will collect the soft referenced objects, so in theory they should never cause an OutOfMemory error. 
Örnek
Şöyle yaparız
List<SoftReference<Object>> lst = new ArrayList<>();
while (true) {
  lst.add(new SoftReference<>(Files.readAllBytes(Paths.get("huge.txt"))));
}