23 Temmuz 2014 Çarşamba

Fork-Join Framework

Fork-Join Nedir?
Verilen işin sürekli daha küçük parçalara bölünerek işlenmesi ve sonucun birleştirilerek elde edilmesidir. Fork-join ve Java 8 ile gelen stream framework bazı açılardan benzeşiyor. Her ikisi de işleri daha küçük parçalara ayırıyorlar. 

ForkJoin anladığım kadarıyla Doug Lea'nin bir makalesi üzerine geliştirilmiş.

ForkJoin Pool sınıfı

ForkjoinPool böl ve fethet yöntemi uygulanabilen işlerde çok faydalı.Diğer thread pool'lardan farklı olarak threadler daemon olarak yaratılıyorlar. Dolayısıyla shutdown() metodunun çağırılmasına gerek kalmıyor.

ForkJoinPool ile iki çeşit ForkJoinTask kullanılabiliyor. Bunlar RecursiveAction ve RecursiveTask.
RecursiveAction ile sonuç dönülemezken, RecursiveTask ile dönülebiliyor. 

Not : ForkJoinPool'un amacı dışında böl ve fethet yöntemi kullanılmadan, sadece bir sabit newFixedThreadPool gibi kullanıldığı bir örnek burada.


RecursiveTask Nasıl Çalışır?

Bu örnekte alt görevler fork() metodu ile başlatılıyor ve join() metodu ile sonuçları birleştiriliyor. Aşağıdaki şekli buradan aldım.

ForkJoin kullanımını eleştiren bir yazıdan ise aşağıdaki şekli aldım.
Result solve(Problem problem) {
       if (problem is small)
         directly solve problem
       else {
        split problem into independent parts
        fork
 new subtasks to solve each part
        join all subtasks
        compose result from subresults
    }
}

invoke Metodu ile Sonuç Nasıl Alınır?
Pool'dan sonucu alma örneği
ForkJoinPool pool = new ForkJoinPool();
Long result = pool .invoke (new MyRecursiveTask()); //Sonucu al
Burada ForkJoinPool kullanımına da bir başka örnek var.
Bu sınıf ile kullanılan RecursiveTask'ın compute(), fork() ve join() metodlarını iyi anlamak lazım. Büyük lokma önce daha küçük parçalara ayrılıyor. Daha sonra küçük lokmaların 1 tanesi hariç, diğerleri iş kuyruğuna ekleniyorlar. Kuyruğa eklenmeyen küçük lokma mevcut thread tarafından çalıştırılıyor.

fork() metodu daha küçük parçaya ayrılan yeni işi kuyruğa ekler. Her thread'in kendi kuyruğu var, ancak gerekirse diğer thread'ler iş çalma (work stealing) yapabilirler.
compute() metodu daha küçük parçaya ayrılan yeni işi kuyruğa eklemeden mevcut thread ile çalıştırır.
join() metodu kuyruktaki çalıştırılan işin bitmesini bekler.



Bir başka örnekte ise verilen dizinin alt dizinlerini listeme var.

RecursiveAction Örneği :
Bu kullanım şekilinde genellikle global tüm action nesneleri tarafından erişilebilen bir nesneye işlem uygulanıyor. Örneği buradan aldım

//Default parallelism level = Runtime.getRuntime().availableProcessors()
ForkJoinPool fjpool = new ForkJoinPool(64);
int arrayLength = 100000000;
int array[] = new int[arrayLength];
RecursiveAction task = new RandomFillAction(array, 0, array.length);
fjpool.invoke(task);

class RandomFillAction extends RecursiveAction {
    int low;
    int high;
    private int[] array;
    splitSize = 40000; //Some threshold size to spit the task
   
    public RandomFillAction(int[] array, int low, int high) {
        this.low = low;
        this.high = high;
        this.array = array;
    }

    @Override
    protected void compute() {
        if (high - low > splitSize) {
            // task is huge so divide in half
            int mid = (low + high) >>> 1;
            invokeAll(Arrays.asList(new RandomFillAction(array, low, mid), 
                                                 new RandomFillAction(array, mid, high))
                          );
        } else {
            //Some calculation logic
            Random random = new Random();
            for (int i = low; i < high; i++) {
                array[i] = random.nextInt(10000);
            }
        }
    }
}  

Bir başka örnekte ise RecursiveAction nesnesi global bir listedeki nesneleri metodlarını çağırıyor. Örnekteki computeDirectly metodu en küçük bölünmenin gerçekleştiği yeri gösteriyor.

ForJoinPool ve Thread Sayısı
ForJoinPool (int parallelism)
ile kaç tane thread ile çalışmasını istediğimizi belirtiyoruz. Örnek:

Eğer parametre vermezsek bu sayı CPU sayısına eşit oluyor. Örnek:

ForkJoinPool ve Thread'in Beklemesi
Buradaki soruda ForkJoinPool'un CPU sayısından daha fazla thread'e sahip olamayacağı yazıyor. Eğer thread'lerden birisi I/O için beklerse, diğer bekleyen işler için yeni bir thread yaratılmıyor. Burada bu konuyu açıklayan şimdiye kadar gördüğüm en iyi cevap var.

5 Temmuz 2014 Cumartesi

Düzenli İfade Örnekleri

Bazı düzenli ifade örneklerini aşağıya ekledim.

Düzenli İfadelerde Kullanılan Özel Karakterler Sınıfları
Özel karakter sınıfları belli bir kümedeki karakterlerle eşleşirler. 
Basit bir şekil aşağıda.

Harfler

[a-z] aralığında boşluk karakteri (space) de aralığa dahildir.

Sayılar
\d ile bir sayı karakteri ifade edilir.

\D ile sayı olmayan bir karakter ifade edilir.
Örnekte "046 55.5" şeklindeki bir telefon numarası non-digit karakterler silinerek "046555" haline getiriliyor.
Regex.Replace(value, @"\D", "") 

Boşluk
\s ile boşluk (space) karakteri ifade edilir. Anladığım kadarıyla \t (tab) karakteri de boşluk olarak kabul ediliyor.

Boşluk olmayanlar 
 \S ile space olmayan karakterler ifade edilir. Örneğin (\S+)\s+(.+?) ile space olmayan bir grup, sonra bir veya daha fazla boşluk, sonra ise yakalamak istediğimiz grubu buluruz. Space olmayan karakterleri [^\\s] şeklinde de ifade edebileceğimizi sanıyorum. 

Kelime
\w ile bir word (kelime) ifade edilir. [A-Za-z0-9_] ifadesinin kısa halidir. string.replaceAll java doesn't work with lookaround regex? örneğinde \w ifadesine { karakterinin dahil edilmediği görülebilir. 

Kelime Olmayanlar
\W \w kısaltmasının tam tersini yapar. Yani alfanümerik olmayan imla işareti gibi "," ";" "." gibi karakterleri bulur.

Çapalar (Anchor)
Çapalar ile düzenli ifade moturu bir sonraki karakteri işlemez. Ama koşulun tutup tutmadığını değerlendirir.

\b ile word boundary ifade edilir. Örneğin \bcat\b ifadesi ile The cat scattered his food all over the room. cümlesinde sadece cat kelimesi ile eşleşilir.
\B \b kısaltmasının tam tersini yapar
^ ile string'in başı belirtilir. Multiline modu kullanılmıyorsa cümle içinde \n karakterini dikkat almaz.

Quantifiers 

Grubun Uzunluğunu Kontrol Etme Örnekleri
0 ila 11 tane arasında olması gerektiğini belirtmek için \d{0,11} yazıyoruz. Tamı tamına 11 tane olması için \d{11} yazıyoruz. Bir başka örnek ise burada.

Eğer bir quantifier  bir kaç defa tekrar edecekse örneğin, parantez içine alma gerekebilir. Örnek:
^(\d{1}){2} // iki defa tekrar etsin
Greedy

Düzenli ifadeler default olarak greedy çalışırlar. Örneğin \s+ ile azami eşleşme yapılırken \s+? ile reluctant çalışması sağlanır. Yani ? işareti greedy çalışmayı engeller.

Escape yapılması gereken özel karakterler
  • { karakteri aslıda "kaç tane"anlamına gelen kısaltma olduğu için - örneğin \d{2}'nin escape ile işaretlenmesi gerekir. Dolayısıyla \d\\{2 şeklinde yazılmalı.
İçerildiğini Bulma Örnekleri
Bir ifadenin içerildiğini bulmak
".*true.*" örneğinde string içinde true kelimesinin geçip geçmediği geçtiği bulunabilir.

Bir veya birkaç karakterin içerildiğini bulmak
.*[x-z].* örneğinde x-z arasındaki (her ikisi de dahil) herhangi bir karakterin içerildiği kontrol edilir.

Bir ifade ile başlanılmadığını bulmak
"^[^\\d].*" örneğinde string'in sayı ile başlayıp başlamadığı bulunabilir

İçeriği Yakalama Örnekleri
Bir ifade ile başlamak ve geri kalanı yakalamak





24 Haziran 2014 Salı

Java Streamleri

BufferedInputStream
close metodu
BufferedInputStream kapanırken kendisine verilen stream'i de kapatır.

17 Haziran 2014 Salı

Sosyal Ağlarda İlişki

Facebook
İki insanın birbirlerine arkadaşlık göndermesi gerekir. Arkadaşlık isteği kabul edildikten sonra birbirlerinin duvarlarına mesaj gönderme (post) ve görme imkanını elde ederler.

Twitter ve Instagram
Daha esnek olan izleyen ve izlenen ilişkisi kullanılır. 

IEEE 754 ve Yuvarlama

Not : Konuyla ilgili olarak IEEE 754 başlıklı yazıya göz atabilirsiniz.

Yuvarlama İşlemleri
Yuvarlama (rounding) küsuratlı sayının tam sayıya çevrilmesi demek. 


Standart Yuvarlama Yöntemleri
Burada yuvarlama formüllerini gösteren güzel bir şekil var. Bir çok programlama dili bu yuvarlama yöntemini metod olarak sunuyor.


Round (Away FromZero) aşağıdaki gibi gerçekleştirilebilir. 

Standart Olmayan Yuvarlama Yöntemleri
Aşağıda programlama dilleri tarafından sunulmayan ve pek te karşımızı çıkmayan yuvarlama yöntemlerini not ettim.

Eksiyi Koruyan Ceil
Buradaki örnekte ceil'in tersine eksi sayılar daha da küçülüyor.
f(0.1) = 1
f(-0.1) = -1
f(0.0) = 0
İki şekilde kodlanabilir.
rounded = Math.ceil(Math.abs(toBeRounded)) * Math.signum(toBeRounded);
veya
rounded = Math.copySign(Math.ceil (Math.abs(toBeRounded)),toBeRounded);


Sayıyı Başka Bir Sayının Katı Olacak Şekilde Yuvarlama
Örneğin 201 gibi bir sayı 300'e yuvarlanır. 14 sayısı 100' yuvarlanır.
Algoritma aşağıdakine benzer
int round (int number,int multiple){
    int result = multiple;

    //If not already multiple of given number
    if (number % multiple != 0){
        int division = (number / multiple)+1;
        result = division * multiple;
    }
    return result;
}
Burada da benzer bir cevap var ancak genel bir algoritma sunmamış.

Bir diğer yöntem ise aşağıda. Kolay okunsun diye parantezleri renklendirdim.
#define ROUND_UP (x,multiple) ( ( (int) (x)+ (multiple -1) ) ) & ~ (multiple -1)

#define ROUNDA_DOWN (x,multiple) ( (int) (x) & ~ (multiple -1) )

C
ceil
ceil() ve ceilf aynı işlevi görürler. Kabaca şöyledirler:
return ( (v < 0.0 ) ? v : (v +1) );

floor
floor() kabaca şöyledir.
return ( (v < 0.0) ? ( v - 1.0) : v ); 

round ve roundf
Bu metodlar verilen kayan sayıyı en yakın integer'a yuvarlar. 

Yuvarlama yönünü fegetround() ve fesetround() metodları ile değiştirebiliriz.

Sayıyı belli bir küsürata yuvarlamak için round() metodu dışında, buradaki  gösterildiği gibi floorf veya ceilf metodları kullanılabilir.

C++
Yuvarlama işlemi fesetround() ile yapılır. Örnek:
Java
Math.Floor ve Math.Ceil metodları var.

Yuvarlama yaparken kaç hane istediğimizi belirtmek istersek aşağıdaki kodu kullanabiliriz.
static Double round(Double d, int precise) {
    BigDecimal bigDecimal = new BigDecimal.valueOf (d);
    bigDecimal = bigDecimal.setScale(precise, RoundingMode.HALF_UP);
    return bigDecimal.doubleValue();
}

C#
Aynı Java'daki gibi Math.Floow ve Math.Ceil metodları var.
Math.Ceiling(num) // Rounds up
Math.Floor(num) // Rounds down
Math.Round ile yuvarlamak yöntemi ve kaç hane istendiği belirtilebilir. Örnek:
Math.Round(value, 2, MidpointRounding.AwayFromZero);
SQL
round metodu ile haç haneye kadar yuvarlama istendiği belirtilebilir.


10 Haziran 2014 Salı

AR-GE

AR-GE projelerinde işin tanımsız olması gerekiyor. Tanımlı işlerin gerçekleşmesi uygulama sayılır.

AR-GE projeleri de normal iş akışını takip ederler

I have a concept or an idea
I draft the concept/idea on paper. 
I do a prototype.
I realize a semi-working version I can use. 
I end up with a working product which is used by me and eventually a few other people.
I ship a stable product to a limited number of people.
The product is a commercial success and achieved to become popular.


6 Haziran 2014 Cuma

Sıralama - Ordering

QuickSort
Quicksort recursive (özyineli) veya sıralı olarak yazılabilir. Burada algoritma dans ile gösteriyor. Açıklaması şöyle
The quicksort algorithm is based on the partitioning procedure. Partitioning procedure works like this: You pick an element from the array to be the pivot. Your array will be divided into two subarrays around the pivot item. Elements larger than the pivot will end up in the right subarray and the ones that are smaller will end up in the left subarray.
...
If you keep applying this partitioning procedure recursively to the left and right subarrays until you reach subarrays of size 1, you will obtain a sorted array. 
Recursive Yöntem
Bu algoritmayı recursive şeklinde aratınca karşımıza bu sayfa çıkıyor. Sayfadaki algoritmada partition metodunda gereğinde fazla swap() yapılıyor. Daha iyi çalışan bir kod ise burada.