27 Şubat 2010 Cumartesi

Threads - Multithreading

Herkese merhabalar;

Bu yazımda multithreading'e değinmeye çalışacağım.Bildiğiniz gibi multithreading i destekleyen diller aynı anda birden fazla taskı çalıştırabiliyorlar ya da aynı taskı birden fazla thread e paylaşarak performans sağlayabiliyorlar.Basit bir Java uygulamasıyla da konuyu pekiştirmeye çalışalım..Benim uygulamam matrix çarpımı üzerine olacak.
Matrix çarpımıyla ilgili gerekli bilgiyi buradan alabilirsinizNormalde tahmin edebileceğiniz gibi sonuç matrixini iç içe for döngüleriyle elde edebilirdik.Ama bizim yapacağımız şey şöyle olacak. NxM 'lik matrixi MxK 'lik matrisle çarpmak istiyoruz.Soldaki matrixi satırlara böleceğiz ve her satırımızı sonuç matrixini oluşturmak için thread 'lere dağıtacağız.Lafı fazla uzatmadan uygulamaya geçeyim:)

public class MyThread extends Thread {
int[][] row;
int[][] coloum;
int index;
public MyThread(int[][] _row, int[][] _coloum, int _index) {
this.row = _row;
this.coloum = _coloum;
this.index = _index;
}
@Override
public void run(){
compute(this.row, this.coloum);
}
public void compute(int[][] _row, int[][] _coloum){
for (int i = 0; i < class="Apple-style-span" color="#000099">length; i++) {
TestClass.resultMatrix[index][0] += _row[0][i] * _coloum[i][0];
}
}
}

Şimdi ne yaptığımıza bir göz atalım.Ben çarpımın sağındaki matrixini Nx1'lik seçtim.Sonuç matriximiz de doğal olarak bir sütun gelecek.Thread 'lere yolladığımız satırları sonuç matrixinin aynı indexteki satırını hesaplamasını istiyoruz.Şimdi kodumuzu test edelim.

public class TestClass {

public static int[][] resultMatrix = new int[3][1];
public static void main(String[] args) {
final int[][] A = {
{1,2,3},
{3,4,1},
{5,2,3}
};
final int[][] B = {
{4},
{3},
{2}
};
MyThread t;
for (int i = 0; i <>
int[][] localRow = new int[1][3];

for (int j = 0; j <>
localRow[0][j] = A[i][j];
}

t = new MyThread(localRow, B, i);
t.start();
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
for (int i = 0; i < resultMatrix.length; i++) {
System.out.println(resultMatrix[i][0]);
}
}
}

Burada dikkat etmemiz gereken nokta main fonksiyonun da bir thread olduğudur.Bildiğiniz gibi join işlemi thread 'lerde schedule ve priority yönetiminde kullanılır.Burda join kullanmasaydık yarattığımız thread 'ler işlemlerini yaparken main fonksiyonu da aynı anda resultMatrix 'i ekrana basmaya çalışacaktı.Böylece ortaya yanlış bir sonuç çıkacaktı.Biz thread 'leri join 'leyerek main fonksiyonun bizim yarattığımız thread 'lerin çalışmasını beklemesini sağladık.Çalıştıralım ve sonucu görelim.


Herkese kolay gelsin :)

26 Şubat 2010 Cuma

Directing to web pages in a desktop application

Herkese merhabalar;

Size console uygulamalarında web sayfalarını nasıl açabileceğimizi göstereceğim.

Java kodu

import java.awt.Desktop;
import java.net.URI;

public abstract class TestClass {
public static void main(String[] args) {
Desktop d;
URI u;
try {
u = new URI("http://www.eclipse.org/");
d = Desktop.getDesktop();
d.browse(u);
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}

C# Kodu

using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Process.Start("
http://www.bing.com/");
}
}
}


Herkese kolay gelsin :)

18 Şubat 2010 Perşembe

Threads - Synchronizing Threads

Herkese merhabalar;

Bu yazımda Thread 'lerimizi nasıl senkron ederiz buna değinmeye çalışacağım.Thread 'lerin senkronlanması çok önemli bir konudur. Thread 'lerle ilgili ilk yazımı okuduysanız Thread 'lerin kendilerine ayrı bellekleri olmadığını ve ortak bir bellek sahası kullandıklarını biliyoruz.Bu ortak bellekleri kullanan Thread 'lerin senkronizasyonunu anlatmaya çalışacağım.

Shared data kullanan Thread 'ler ortak veriye erişmek için yarış halindedirler.Bu duruma race condition denir.Bu race condition 'un çözülmesi önemli bir problemdir. Java bize bu problemi çözmek için syncronized anahtar kelimesini sağlıyor.Thread 'lerin ortak kullandığı kod bölgelerine critical section da denir.Critical section 'larda bu anahtar kelimeyi kullanmak mutex lock algoritmasından başka birşey değildir.Buradan bilgi alabilirsiniz.

Şimdi bir örnek üzerinde kavramları da açıklayarak konuyu anlamaya çalışalım. Örneğimiz şöyle olsun.Bir banka hesabımız olsun bu banka hesabından para çekmek isteyen Thread 'lerimiz olsun.Ve para çekme koşulumuz da tabii ki çekilmek istenen paranın banka hesabında olması olsun.

public class Account {

public float total = 0;
public Account() {}
public synchronized boolean drawCash(float amount){
if (total > amount) {
System.out.println("Aktif thread = "+Thread.currentThread().getName())
total = total- amount;
return true;
}
else
return false;
}
}

public class MyThread extends Thread {

private Account myAccount;
private float amount;
public MyThread(Account _myAccount,float _amount) {
setMyAccount(_myAccount);
this.amount = _amount;
}

@Override
public void run(){
if (getMyAccount().drawCash(this.amount)) {
System.out.println(this.getName()+"->Değişikliği yaptı. Total ="+getMyAccount().total+"Amount ="+this.amount );
}
else {
System.out.println(this.getName()+"->Değişikliği yapamadı."+"Total ="+getMyAccount().total+"Amount =" +this.amount);
}
}

public void setMyAccount(Account myAccount) {
this.myAccount = myAccount;
}

public Account getMyAccount() {
return myAccount;
}
}
Evet ne yaptığımıza bakalım.Thread 'lerimiz banka hesabımızı ortak kullanıyor olacaklar.Ve burda kritik bölgemiz threadlerimizin ortak kullandığı data olan total değişkeni üzerinde değişiklik yapan metod olan drawCash metodu kullanmak için bir yarış halinde olacaklardır.Ancak drawCash işlemi içinde bir koşul barındırıyor.Bu da çekilmek istenen paranın hesabımızda mevcut olması durumudur.İşte kritik nokta burada başlıyor.Eğer threadler aynı anda bu bölgeye ulaşırsa ve threadlerin istediği toplam para hesabımızda yoksa ne yapacağız?Bu problemimizi syncronized anahtar sözcüğü çözüyor.:) MyThread sınıfımızda ise yarattığımız threadler Account'umuzdan para düşmeye çalışcaklar.

Şimdi yazdığımız kodu test edelim.

public class TestClass {

public static void main(String[] args) {
Account myAccount = new Account();
myAccount.total = 150;
MyThread t1 = new MyThread(myAccount, 100);
t1.setName("Thread 1");
MyThread t2 = new MyThread(myAccount, 75);
t2.setName("Thread 2");
t1.start();
t2.start();
}
}

Kodu çalıştırdığımızda threadlerin hangisi critical section'a erken ulaşırsa ilk onun istediği para hesabımızdan düşecektir.Yani 2 farklı çıktı elde edeceğiz.Bunun sebebi ise aynı hiyerarşide olan ve aynı anda çalıştırılan threadlerin çalışma süresi ve sırası nondeterministic'tir.

1.Çıktı->
Aktif thread = Thread 2
Thread 2->Değişikliği yaptı. Total =75.0Amount =75.0
Thread 1->Değişikliği yapamadı.Total =75.0Amount =100.0
2.Çıktı->
Aktif thread = Thread 1
Thread 1->Değişikliği yaptı. Total =50.0Amount =100.0
Thread 2->Değişikliği yapamadı.Total =50.0Amount =75.0

Görüldüğü üzere critical section'da aynı anda sadece bir tane thread aktif olabiliyor.Böylece banka hesabımızda
yanlış bir durumdan kaçınmış oluyoruz.Ve şimdi Account sınıfımızda drawCash metodumuzdaki syncronized
anahtar kelimesini kaldıralım ve neler oluyor görelim.

Çıktı->
Aktif thread = Thread 2
Aktif thread = Thread 1
Thread 2->Değişikliği yaptı. Total =-25.0Amount =75.0
Thread 1->Değişikliği yaptı. Total =50.0Amount =100.0

Bir gariplik var gibi değil mi?..:) Bir hesabımızdaki paranın çekilmek istenen paradan büyük olması
koşulunu parayı çekmek için koyduk ama total = -25 gelmiş.Ve dikkatinizi çektiyse aynı anda
critical section'da threadlerimizin ikisi de aktif.İşte bu yüzden threadlerin senkron edilmesi
çok önemli bir konudur.

Önemli Not : Çıktıları elde etmek için bir kaç defa kodunuzu çalıştırmanız gerekebilir.
Çünkü daha önce de söylediğim gibi aynı anda çalıştırılan ve aynı hiyerarşiye sahip
threadlerin çalışması nondeterministic olduğu için bir kaç defa aynı çıktıyı elde edebilirsiniz.


Herkese kolay gelsin :)

14 Şubat 2010 Pazar

Threads - Creating Threads

Herkese merhaba ;

Size Java threadlerinin nasıl yaratıldığını, nasıl kullanıldığını anlatmaya çalışacağım.Threadleri kullanmanın 2 temel yolu vardırYa Thread sınıfından bir instance yaratarak kullanabiliriz.Ya da thread tasklarını bir başka sınıfa abstract olarak geçirerek.

Aşağıda Thread tasklarını başka sınıflara geçirerek kullanmanın 2 farklı yolu gösterilmiştir.
Neden 2 farklı şekilde task aktarımı var derseniz.Eğer programınızda GUI kullanmanız gerekirse sınıfınız Frame sınıfından türemek zorundadır ya da bir kalıtım hiyerarşisi içindeki sınıfta Thread kullanmak isteyebilirsiniz.Böyle durumlarda ilgili sınıflara Runnable interface'ini implement etmeniz gerekir.İki kullanımın tek farkı burdur.

public class MyThread extends Thread {

@Override
public void run(){
//Foo
}
public static void main(String[] args) {
new MyThread().run();
//Ya da new MyThread().start();
}
}

ya da

public class MyThread implements Runnable {

@Override
public void run(){
//Foo
}
public static void main(String[] args) {
new MyThread().run();
}
}

Bir Threadin Yaşam Döngüsü
Threadler 3 farklı durumda olabilir.
New Thread : Bu durum ilklenmeden sonra start() metodu çağırılmadan önceki durumdur.
Alive Thread : Bu durum start() metodu çağırıldıktan sonraki durumdur.Bu durum da kendi içinde 2 duruma ayrılır.
-> Runnable : Çalışma halidir.Bu durumda thread ya çalışıyordur ya da çalışmak için sırasını bekliyordur.
-> Blocked : Çalışmaya hazır olmadığı durumdur.Bu durumdan çıkılabilecek koşullar sağlandığında runnable'a geçebilir
Dead Thread : run() metodu tamamlandığındaki durumdur.Bu state e giren thread tekrar çalıştırılamaz.

Thread Sınıfının Çok Kullanılan Metotları
start() : Thread,New durumundır ve bu metot threadi Alive durumuna sokar.Threadi çalıştırır.
stop() : Thread,Runnable durumundır ve bu metot threadi Blocked durumuna sokar.Threadin çalışmasını durdurur.
join() : Thread, Runnable durumundır ve threadi Blocked durumuna sokar ve thread başka bir threadin bitmesini bekler.Diğer thread çalışmasını bitirince tekrar Runnable durumna girer.
interrupt(): Thread,Runnable durumundır ve threadi Blocked durumuna sokar.Ve threadin tekrar Runnable durumuna geçmesi için programcı tarafından resume() edilmesi gerekir.
isAlive(): Thread Alive durumunda ise bu metot true döndürür.
isInterrupt(): Interrupt flagi set edilmişse true döndürür.

Şimdi bir basit örnek çözelim. Bir counter tutalım sürekli 10'a kadar sayıp başa dönsün.

public class MyThread extends Thread{

int seconds = 1;
@Override
public void run(){
for(;;){
System.out.println("seconds : "+seconds);
if (seconds == 10) {
System.out.println("Başa dön!");
seconds = 0;
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
seconds++;
}
}
public static void main(String[] args) {
new MyThread().start();
}
}

Herkese kolay gelsin :)




13 Şubat 2010 Cumartesi

Threads - Intro to Concurrent Programming

Herkese merhabalar;

Bu yazımda size threadlerin(iş parçacığı) ne olduğunu nasıl kullanıldığından bahsetmeye çalışacağım.Ama önce process ve thread kavramlarını kısa olarak bir özetleyelim.
Process : Processler bütündür.Kendine tahsis edilmiş özel bellekleri vardır.Ve genellikle programlara veya uygulamalarla senkron bir şekilde çalışırlar.
Thread : Threadler ise processler içinde bulunur.Ve aynı processler gibi bir execution environment sağlar.Ancak süreçlerden farkı kendilerine ait özel bir bellekleri yoktur.Bu yüzden threadlere light-weight process de denir.

Thread bir programdaki kontrolün sıralı olarak(sequential) akışıdır.Bir çok geleneksel programlama dili ya single-threaded ya da sequential'dır.Yani aynı anda sadece tek bir task'ı işleyebilir.

Eş zamanlı programlama(concurrent programming) ,yani multithreaded programming, bize aynı anda birden fazla taskı işlemeyi sağlar.Peki neden multithread..? Bu sorunun cevabı aslında basit.Tabii ki zaman ve maliyet.Teoride bir sürece daha fazla kaynak tahsis etmek işlemi kısaltır.Ancak multithreading daha ucuza işlemleri tamamlayabilir.

Herkese kolay gelsin :)