#runnable etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster
#runnable etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster

17 Kasım 2019 Pazar

Thread Safety HashMap

Merhaba,
Bu yazida thread safe hashmap ile ilgili ornek yapacagiz.
Once thread safe olmayan bir ornek yapalim.

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class UnsafeMap {
 public static void main(String[] args) throws InterruptedException {
  Map cricketMap = new HashMap();
  cricketMap.put("Australia", 349);
  cricketMap.put("India", 257);
  ExecutorService executorService = Executors.newFixedThreadPool(10);
  Runnable task = new Runnable() {
   @Override
   public void run() {
    incrementScore(cricketMap, "India");
   }
  };
  for(int i=0; i<100 :="" ap="" cricketmap.get="" executorservice.awaittermination="" executorservice.shutdown="" executorservice.submit="" i="" inal="" incrementscore="" india="" integer="" is="" ndia="" of="" private="" score="" static="" system.out.println="" task="" timeunit.seconds="" tring="" void=""> teamMap, String team) {
  Integer score = teamMap.get(team);
  teamMap.put(team, score +1);
 }
}

Yukaridaki ornekte India nin score unu 100 arttirdik. Sonucun 258 olmasini bekliyoruz ama her seferinde baska sonuc cikiyor.

Final score of India is : 353
Final score of India is : 352

gibi. Neden ?

Cunku 

since multiple threads try to modify the HashMap concurrently, the change done by one thread gets overridden by some other thread, and the output becomes non-deterministic.

Bunu onlemek icinse ornegimizi thread safe yapalim. Yani sadece ayni anda tek bir thread erisebilsin. Bunun icin yapacagimiz iki sey sunlar olmali :

  • Use the Collections.synchronizedMap() method to obtain a synchronized view of the HashMap.
  • Write the increment logic inside a synchronized block.
Son halde kodumuz su sekilde olur:

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class Safemap {
 public static void main(String[] args) throws InterruptedException {
  Map cricketScore = Collections.synchronizedMap(new HashMap());  
  cricketScore.put("Turkey", 52);
  cricketScore.put("Germany", 170);   
  //we are creating thread pool with size 10
  ExecutorService executorService = Executors.newFixedThreadPool(10);
  
  Runnable task = new Runnable() {   
   @Override
   public void run() {
    incrementScore(cricketScore, "Turkey");    
   }
  };
  for(int i=0; i<100 :="" ap="" cricketscore.get="" executorservice.awaittermination="" executorservice.shutdown="" executorservice.submit="" i="" inal="" incrementscore="" integer="" is="" of="" private="" score="" static="" system.out.println="" task="" timeunit.seconds="" tring="" turkey="" urkey="" void=""> scoreMap, String team) {
  synchronized (scoreMap) {
   Integer score = scoreMap.get(team);
   scoreMap.put(team, score +1);
  }
 }
}
Turkiyenin score unu 100 arttirdik. Threas safe oldugu icin her zaman 152 donecektir.

Final score of Turkey is : 152

9 Kasım 2019 Cumartesi

Multithreading Java

5 defa Hi, 5 defa Hello yazdiralim.



Output: Hi
Hi
Hi
Hi
Hi
Hello
Hello
Hello
Hello
Hello


Gordugumuz gibi 5 kez Hi ve Hello yazdi. Simdi ise her bir yazmadan once biraz beklesin diye bi thread sleep koyalim. 500 verdim yani 500 ms.




Kodumuz bu sefer yukaridaki gibi. 500 ms arayla print ediyor. Burada belirtmek istedigimiz sey kodumuz yine ayni seyi yapiyor ancak Hi yazmasinin bitmesini bekliyor. Bitmeden Hello ya gecmiyor. Bizim istedigimiz ise ikisi ayni anda calisabilsin, birbirini bloklamasin.

O yuzden burada thread kullanacagiz. Her classimiz Thread classini extend ederse classlarimiz Thread haline gelmis olur. Eee Thread classlarinda mutlaka run() olmali ki islemimiz orada calissin. O yuzden show() metodunu run() haline getiriyoruz. ve main threadimiz obj1.start() dememiz lazim. start() cagirdigimiz anda gidip run() methodunu calistirir.



Output  :
Hi
Hello
Hi
Hello
Hello
Hi
Hi
Hello
Hello
Hi

Gordugumuz gibi artik 2 thread birbirini beklemiyor ve ayni anda calisabiliyor. Hatta o kadar ayni ana denk gelmis ki ardarda 2 tane Hello goruyoruz. Ayni ana gelme durumlarinda schedular a gidilir ve schedular hangisi daha kisa ve kolaysa onu secer. Ancak burada 2 methodumuz da ayni islemi yaptigi icin random olarak Hello secilmis.


Interfacelerle Calismak

Javada asagidaki gibi bir kullanim yoktur.

class A extends B, C

Sadece bir tane extend edebiliriz.

O halde soyle bir sey yapmak yerine

class Ornek extends A, Thread { (hatali)

asagidaki gibi yapabiliriz.

class Ornek extends A implements Runnable {

Yani neymis : Thread olusturmanin 2 yontemi varmis.

1. extends Thread diyerek

2. implements Runnable diyerek

Hangisi isimizi gorurse onu kullanmaliyiz.

O halde ornegimizi bir de bu sekilde deneyelim.

Ancak artik classlarimiz Thread tipinde olmadigi icin obj1.start() diyemeyiz. Hata verir. Runnable da o sekilde bir method yok.

O zaman Thread olusturmamiz lazim.

Thread t1 = new Thread(obj1);
t1.start();

iste bu calisir. O halde kodumuzu duzenleyip yeniden deneyelim.



Output:
Hi
Hello
Hello
Hi
Hello
Hi
Hi
Hello
Hello
Hi

Lambda Expressions

Simdi de bu yazmis oldugumuz daha kisa ve daha efektif hale getirmeye calisalim.

Hi ve Hello adinda iki class yazdik ve ikisinin de yaptigi sey sadece Runnable i implement etmek. O halde bunlara gerek yok.Thread icinde de ayni islemi yapabiliriz.



Simdi de bunu lambda haline getirelim. Yani method isimlerine ve parantezlere gerek yok.

O durumda da soyle olur:


Son durumda ise kodumuz asagidaki gibi olur ve ayni islevi daha efektif olarak yapar.


Output:

Hi
Hello
Hello
Hi
Hi
Hello
Hi
Hello
Hi
Hello