Java İle Multithreading Paralel Kullanimı ve Java Utilities Paketi ve Bit işlemleri
Multitasking ile Multithreading Arasinda Ne Fark Vardir?
Ilk zamanlarda bilgisayarlar belirli bir anda sadece bir isi yapabilir yetenekteydi. Ornegin, bir labaratuvardaki bilgisayar once fizikci icin dalgalarin gecikme suresiyle ilgili hesabi yapacak,
daha sonra kimyaci icin karisim oranlarini hesaplayabilecekti. Tum programlar, belirli bir sira dahilinde ve belirli bir anda bilgisayarin sadece birinin hizmetine verilmesi seklinde calistiriliyordu. Ayni anda birden fazla programin icrasi soz konusu degildi. Bu teknige batch processing denir ve pahali bir bilgisayarin max faydada kullanimi adina oldukca etkili bir yontemdir. Cunku bu yontemde bilgisayarin tum kaynaklari islem yapmak icin kullanilmakta, birden cok is arasinda gelgitler yapilmasindan dolayi gelecek zaman ve performans kaybi engellenmis olacaktir. Fakat batch processing bir sistemin negatif bir yonu de vardir. Ornegin nükleer yapi modellemesi yapan ve 3 gun icinde hayata gecirilmesi planlanan bir projenin bir parcasi olan diferansiyel denklem programi CPU zamaninin buyuk bir kismini kullanir ve bir satirda takilip tum sistemi kullanilmaz hale getirirse, bu durum hic de arzulanmayacak bir durum olacaktir.
Zaman paylasimli isletim sistemlerinin gelistirilmesi, birden cok kullanicinin ayni anda pahali bir bilgisayari kullanimini mumkun hale getirmistir. Boyle bir sistemle birden cok kullanici programlarini ayni anda calistirabilir. Isletim sisteminin gorevi, islemci zamanini bu programlar arasinda paylastirmaktir. Az once verilen ornege geri donulurse; diferansiyel denklemlerin
hesaplanmasi ile fizik departmanindaki nükleer modelleme programi ayni anda calistirilabilir. Belki bu nukleer modelleme programi 3gunde degil de 2 haftada tamamlanir ancak her iki iste de
yavas ama tatminkar sonuclar elde etmek mumkun olur. Buna karsilik sistemi ayni anda kullanma istegi sadece kullanicilardan gelmez. Ayni zamanda bircok programda birden cok isi bir arada yapma gereksinimi duyabilir. Mesela web gezgininde geri planda bir sayfa yazdirilirken bir pencerede de sayfa yuklenirken formatlanabilir. Iste tek basina bir programin birden fazla isi ayni anda yapabilmesi thread kullanimi sayesinde gerceklesir.
Giris
Java programlama dilininin en onemli ozelliklerinden biri de Multithreaded Mimariyi destekliyor olmasidir. Bu mimari, bir bilgisayar programinin komutlarinin icrasinin kontrolunu ve iyilestirilmesini sagladigi icin bilgisayar bilimleri acisindan cok guclu ve hatiri sayilir bir gerceklestirim olarak degerlendirilmelidir. Java da bu mimariyi icerisinde barindirma özelligi ile benzerlerinden ayrilan, en cok kullanilan, genel amacli programlama dillerinden biridir. Diger programlama dillerinde olmayan (ancak isletim sisteminin destekledigi) “eszamanli calisma prensipleri” (concurrency primitives) bu dilin yapisi icerisinde PC uygulama gelistiricisine sunulmaktadir. Uygulama gelistiricinin gorevi, uygulamalari icra bloklarina(threads of execution) ayirmaktir. Burada her blok diger bloklarla es zamanli olacak sekilde kendi basina icra edilir. Iste bu mekanizma multithreading mekanizmasi olarak adlandirilir. Java programlama dilini
benzerleri olan C and C++ a göre daha guclu kilacak olan mekanizmada budur. Bu diller, belli bir zamanda ancak bir blogun icra edilmesini desteklemektedir. Es zamanli uygulama gereksinimi duyulabilecek alanlara ornek verelim : Ornegin bir program WWW uzerinden, cok buyuk bir video clip ya da ses clip dosyasini indirirken, dosyanin iceriginin gorulebilmesi icin tamaminin yuklenmesini beklemek kullanici acisindan hic de iyi bir durum degildir. Iste bu durumda coklu icra bloklarina basvurulabilir. Bir icra blogu dosyanin indirilmesi(yuklenmesi) ile mesgul olurken, es zamanli calisan bir baska icra blogu dosyayinin iceriginin goruntulenmesi ile mesgul olabilir. Burada yuklenmis olan dosya parcasinin iceriginin duzgun olarak goruntulenmesi icin icra bloklari arasinda bir koordinasyondan bahsetmek gerekir. Bir baska ornek de; Java ile birlikte gelen otamatik “automatic garbage collection” yapisidir. Bir garbage collector thread araciligiyla icra edilen programin dinamik olarak bellekte isgal ettigi sahalar yine dinamik olarak kullanilmadigi zaman bir baska is icin kullanilmak uzere serbest birakilir. Bu thread dusuk-oncelikli olarak calismaktadir.
Java, dunyanin en populer tasinabilir programlama dillerinden birisi olmasina ragmen bazi belirli kisimlari platform bagimli olarak calismaktadir. Dolayisiyla, coklu thread uygulamalari farki
Java implemantasyonlarinda farkliliklar gosterebilir. 32-bit olarak gelistirilen ve Windows 95 ve Windows NT uzerinde calisan Java uygulamalari zaman paylasimli olarak calismaktadir(timesliced). Round-Robin algoritmasinin kullanilmasi ile, her icra blogunun her seferinde bir zaman araligi boyunca icra gormesi saglanmaktadir.
Thread Nedir?
Thread birbirinden ayrik ayni anda meydana gelmekte olan diger olaylardan bagimsiz olarak icra edilebilen kod topluluklaridir. Bir thread, A noktasinda calistirilmaya baslanan ve B noktasina kadar calismaya devam eden klasik bir program olarak nitelendirilebilir. Fakat thread in farkli olabilecek olan yani, yapisinda bir olay dongusune yer vermeyecek olusudur. Bir thread,sistemde meydana gelen diger olaylardan bagimsiz olarak calisir.
Basit bir thread uygulamasi
Thread leri kullandiginiz bir program yazarken herbiri kendi run() metoduna sahip olan farkli farkli programlar yaziyormus gibi dusunebilirsiniz. Kullanacaginiz her thread java.lang.Thread sinifinin bir alt sinifi olacaktir. Asagidaki program threadlerden olusmustur ve -128 ile 127 arasindaki sayilari ekrana yazdirmaktadir.
public class BytePrinter extends Thread {
public void run() {
for (int b = -128; b < 128; b++) {
System.out.println(b);
}
Asagidaki program da tek bir BytePrinter thread inin icrasini saglamak uzere tasarlanmistir :
public class ThreadTest {
public static void main(String args[]) {
BytePrinter bp = new BytePrinter();
bp.start();
}
Coklu Thread uygulamasi
Asagidaki program da 3 tane BytePrinter thread calistirabilir ozelliktedir:
public class ThreadsTest {
public static void main(String args[]) {
BytePrinter bp1 = new BytePrinter();
BytePrinter bp2 = new BytePrinter();
BytePrinter bp3 = new BytePrinter();
bp1.start();
bp2.start();
bp3.start();
}
}
Programin cikti sirasi programdan anlasilabilecegi uzere tasarim bagimlidir ve cogunlukla onceden tayin edilemeyecek bir goruntu sergilemektedir. Bu durumda 3 thread biri digerini takip
eder sekilde sirayla calistirilir. Buna karsilik bazi sistemlerde de asagidakine benzer bir cikti goruntusu ile karsi karsiya kalinabilir : Bu durumda ise 3 farkli thread den gelen sonuclar kendi aralarinda karismistir. Bazi sistemler biribiri ile koordinasyon icinde calisan thread ler kullanir, bir thread de digerine gecilmesi calismakta olan thread in kontrolu diger thread e aktarmasi yoluyla gerceklesir. Esit oncelikli bir thread bile kendisinden onceki thread in tamamlanmasini beklemek zorundadir. Diger sitemler ise ayni oncelge sahip olan threadler arasinda zaman paylasimi yontemine basvurmaktadir. Bu paylasima ragmen thread lerin ciktilari arasinda bir karisiklik gorulmez.
Java Utilities Paketi ve Bit işlemleri
Bu bölümde java.util paketindeki bazi utilility class'lari incelenecektir. Ilk önce Vector class'i incelenecektir. Vector class'i array benzeri bir yapidir ve dinamik olarak büyüyüp küçülebilmektedir. Programda veri saklamak için kullanilir. Ayrica vector'lerin Enumeration özelliklerini kullanacagiz. Enumeration vector'ün içerigini gezmemizi saglar. Ikinci olarak Stack class'ini inceleyecegiz. Stack class'i vectore benzer fakat çalisma sekli farklidir. Stack class'i push ve pop gibi methodlar sunmaktadir. Daha sonra Dictionary class'ini inceleyecegiz. Dictionary anahtarli veriler saklarken bize anahtar veri erisimini saglamak için bize bir yapi olusturmaktadir. Dictionary'den sonra Hashing teorisini inceleyecegiz ve hemen arkasindan da bu teoriyi uygulamamizi saglayan Hashtable class'ini inceleyecegiz. Hashtable sayesinde verileri bir anahtar yardimiylar veri ortamina atip daha sonra hizli bir sekilde bu verilere ulasabilmekte-
yiz. Bundan sonra da Properties class'ini inceleyecegiz. Bu cla ss Hashtable'dan farkli olarak dissal bir dosyaya yazma ve okuma olanagi saglamaktadadir. Daha sonraki bölümlerde Random class'ina göz atacagiz. Bu class Math.random ile bize saglanan rastgele sayi üretiminden daha zengin bir sayi üretimi saglar. Son olarak da bit islemlerini ayrinitili bir sekilde inceleyecek ve bize bit array benzeri yapi saglayan BitSet class'ini inceleyecegiz.
Vector Class'i ve Enumeration Özelligi
Java dahil birçok programlama dilindeki arraylar statik bir yapiya sahiptir ve programin veri sahasi ihtiyacinin artip azalmasina göre degismezler. Dolayisiyla bazi sorunlar çikar. Buna karsilik Vector class'i çalisma esnasinda kapasitesi degisebilen bir yapi sunar ve bu problemleri ortadan kaldirir. Vector, herhangi bir anda ya kapasitesi kadar yada daha kapasitesinin daha altinda veri bulundurur. Kapasite Vector için bellekte ayrilmis olan yerdir. Vector'deki veri sayisi kapasitesinden azken yeni bir eleman eklemek hizli bir operasyondur. Veri sayisi kapasiteye esitken veri eklemek kapasiteyi artiracagindan yavas bir operasyondur. Eger herhangi bir kapasite artisi verilmediyse Vector kapasitesi default olarak iki katina çikarilacaktir.
=========================================================================================================================================
Örnek: Vector Kullanan Applet
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import java.applet.Applet;
public class VectorTest extends Applet
implements ActionListener {
private Vector v;
//Görsel elemanlar
private TextField input;
private Button ekleBtn, silBtn, ilkBtn, sonBtn, bosBtn,
mevcutBtn, konumBtn, trimBtn, statsBtn, displayBtn;
public void init()
{
v = new Vector(1);
add( new Label("Bir string giriniz: "));
input = new TextField(10);
add(input); //Eklenecek, silinecek veya konumu bulunacak deger
ekleBtn= new Button("Ekle");
ekleBtn.addActionListener(this);
add(ekleBtn); //Girilen string ekleniyor
silBtn= new Button("Sil");
silBtn.addActionListener(this);
add(silBtn); //Girilen string bulunup siliniyor
ilkBtn= new Button("Ilk");
ilkBtn.addActionListener(this);
add(ilkBtn); //Ilk string görüntüleniyor
sonBtn= new Button("Son");
sonBtn.addActionListener(this);
add(sonBtn); //Son string görüntüleniyor
bosBtn= new Button("Bos");
bosBtn.addActionListener(this);
add(bosBtn); //Vector'ün bos olup olmadigi sorgulaniyor
BY Ahmet Tolga Tat Sayfa 97
mevcutBtn= new Button("Mevcut");
mevcutBtn.addActionListener(this);
add(mevcutBtn); //Girilen stringin var olup olmadigi sorgulaniyor
konumBtn= new Button("Konum");
konumBtn.addActionListener(this);
add(konumBtn); //Girilen stringin konumu ögreniliyor
trimBtn= new Button("Trim");
trimBtn.addActionListener(this);
add(trimBtn); //Vector kapasitesi size'ina çekiliyor
statsBtn= new Button("Istatistikler");
statsBtn.addActionListener(this);
add(statsBtn); //Istetistikler gösteriliyor
displayBtn= new Button("Görüntüle");
displayBtn.addActionListener(this);
add(displayBtn); //Vector'ün içerigi görüntüleniyor
}
public void actionPerformed( ActionEvent e)
{
if (e.getSource()== ekleBtn) {
v.addElement( input.getText() );
showStatus( "Sona eklendi: " +input.getText() );
}
else if (e.getSource()==silBtn) {
if (v.removeElement(input.getText()))
showStatus(" Silindi: "+input.getText());
else
showStatus( input.getText()+" vector'de degil");
}
else if (e.getSource()== ilkBtn) {
try {
showStatus("Ilk eleman: " + v.firstElement());
}
catch (NoSuchElementException exception ) {
showStatus ( exception.toString());
}
}
else if (e.getSource()== sonBtn) {
try {
showStatus("Son eleman: " + v.lastElement());
}
catch (NoSuchElementException exception ) {
showStatus ( exception.toString());
}
}
else if (e.getSource() == bosBtn) {
showStatus(v.isEmpty() ? "Vector Bos" : "Vector bos degil");
}
else if (e.getSource()==mevcutBtn) {
String searchKey = input.getText();
if (v.contains( searchKey) )
showStatus(searchKey + " vectorde mevcut" );
else
showStatus(searchKey + " vectorde mevcut degil");
}
else if (e.getSource()==konumBtn) {
showStatus("Eleman "+ v.indexOf(input.getText())+" konumunda");
}
else if (e.getSource()== trimBtn) {
v.trimToSize();
showStatus(" Vectorün kapasitesi eleman sayisina çekildi");
}
else if (e.getSource()==statsBtn) {
showStatus("Eleman sayisi= " + v.size() +"- kapasite = " +v.capacity());
}
else if (e.getSource()== displayBtn) {
Enumeration enum= v.elements();
StringBuffer buf = new StringBuffer();
while ( enum.hasMoreElements())
buf.append(enum.nextElement()).append(" ");
showStatus( buf.toString());
}
input.setText("");
=========================================================================================================================================
- Örnegin kodunu incelediyseniz kodu incelemeye geçebiliriz. Appletin init metodu asagidaki ifade ile yeni bir vector yaratmaktadir.
Vector v = new Vector( 1 );
- Bu ifade ile vector 1 kapasitesinde olusturulmustur. Vector'un her kapasite artisi ihtiyacinda vector kapasitesi iki katina çikarilacaktir. Eger parametre kullanilmasaydi 10 ilk kapasitesi ile olusturulacakti. Ayrica ikinci parametre de kullanilabilirdi. Bu ikinci parametre de kapasite artisidir.
v.addElement( input.getText() );
- Yukaridaki ifade addElement metodunu kullanmaktadir ve Vector'e yeni eleman eklemektedir. Ayrica insertElementAt metodu da vardir. Bu method Vector istenilen yerden eklemeyi saglar. setElementAt metodu ise herhangi bir yerdeki elemani degistirmeye yarar.
v. removeElement();
- Yukaridaki ifade ise Vector'deki ilk elemani silmektedir. Eger eleman silinebilirse metod true degerini döndürür. Eger eleman bulunamazsa false degerini döndürür. Bu silme islemi sonrasinda Vector deki diger elemanlar birer index öne alinir. Ayrica Vector removeAllElements ve removeElementAt metodlarini da saglamaktadir. Bunlar ise Vector tamamen temizlemek ve belli bir indexteki elemani silmek için kullanilir.
v. firstElement();
- Bu ifade Vector'deki ilk elemana referans döndürmektedir. Eger Vector'de eleman yoksa NoSuchElementException'u olusturmaktadir.
v. lastElement();
- Bu ifade de ayni firsElement gibi çalismaktadir. Tek farki ilk eleman yerine son elemana bir referans döndürmesidir.
v. isEmpty();
- Bu ifade eger Vector bossa true degerini aksi takdirde false degerini döndürür.
v. contains(searchKey);
- Bu metod ise searchKey eger Vector de var ise true yok ise false degerini döndürmektedir. Bu metod objenin equals metodunu kullanmaktadir. Bunun amaci bir esitligin var olup olmadigini kontrol etmekdir.
v. indexOf( input.getText() );
- Bu ifade ise Vector'ün indexOf metodunu kullanmaktadir. Girilen elemanin indexini döndürür. Eger girilen eleman bulunamazsa -1 degerini döndürür. Bu metodla aramanin nerden baslayacagida belirtilebilir.
v. TrimToSize();
- Bu ifade kapasitenin Vector'deki eleman sayisina çekilmesini saglar.
v. size();
v. Capacity();
- Bu ifadeler ise Vector'deki eleman sayisini ve kapasiteyi döndürür.
Enumeration enum = v. elements()
- Bu ifade Vector'ün elemanlarindan olusan bir Enumeration olusturur. Enumeration Vectorun elemanlarinin gezilmesini saglar.
enum.hasMoreElements();
enum.nextElement();
Bu ifadeler Enumeration da eleman kalip kalmadigini sorgulamak ve bir sonraki elemana ilerlemek için kullanilir. Vector'ler hakkinda daha çok bilgi için Java API dökümantasyonunu inceleyebilirsiniz
Stack Class'i
Stack class'i Vector class'ini genisletmektedir. Tek farki elemanlari alis veris sirasindaki farkliliktir. Stack de lifo mantigi çalismaktadir. Yani son giren ilk çikmaktadir. Vector de ise ilk
giren ilk çikmaktadir. Asagida da Stack içeren örnek applet'i inceleyebilirsiniz.
=========================================================================================================================================
Örnek: Stack Kullanan Applet
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import java.applet.Applet;
public class StackTest extends Applet
implements ActionListener {
private Stack s;
//Görsel elemanlar
private TextField input;
private Button pushBtn, popBtn, peekBtn, bosBtn, aramaBtn,
goruntuleBtn;
public void init()
{
s = new Stack();
add( new Label("Bir string giriniz: "));
input = new TextField(10);
input.addActionListener(this);
add(input); //Push edilecek veya aranacak string
pushBtn= new Button("Push");
pushBtn.addActionListener(this);
add(pushBtn); //Girilen tepeye string ekleniyor
popBtn= new Button("Pop");
popBtn.addActionListener(this);
add(popBtn); //tepedeki string aliniyor
peekBtn= new Button("Peek");
peekBtn.addActionListener(this);
add(peekBtn); //Tepedeki string'in degeri ögreniliyor
bosBtn= new Button("Bos");
bosBtn.addActionListener(this);
add(bosBtn); //Stack'in bos olup olmadigi sorgulaniyor
aramaBtn= new Button("Arama");
aramaBtn.addActionListener(this);
add(aramaBtn); //Girilen stringin var olup olmadigi ögreniliyor
goruntuleBtn= new Button("Görüntüle");
goruntuleBtn.addActionListener(this);
add(goruntuleBtn); //Stack'in içerigini görüntülüyor
}
public void actionPerformed( ActionEvent e)
{
if (e.getSource()== pushBtn)
showStatus("Push edildi: "+s.push(input.getText()));
else if (e.getSource()==popBtn) {
try {
showStatus("Pop edildi: "+s.pop());
}
catch (EmptyStackException exception) {
showStatus( exception.toString());
}
}
else if (e.getSource()== peekBtn) {
try {
showStatus( "Tepedeki: "+ s.peek());
}
catch (EmptyStackException exception) {
showStatus( exception.toString());
}
}
else if (e.getSource()== bosBtn) {
showStatus( s.empty() ? "Stack bos" : "Stack bos degil");
}
else if (e.getSource()==aramaBtn) {
String searchKey = input.getText();
int result = s.search(searchKey);
if (result==-1)
showStatus( searchKey + "Bulunamadi");
else
showStatus( searchKey +" "+result+" indexinde bulundu");
}
else if (e.getSource()== goruntuleBtn) {
Enumeration enum =s.elements();
StringBuffer buf = new StringBuffer();
while (enum.hasMoreElements())
buf.append( enum.next Element()).append(" ");
showStatus(buf.toString());
}
=========================================================================================================================================
- Simdi biraz programin kodunu inceleyelim.
s.push();
- Bu ifade Stack'in tepesine yeni bir eleman ekler.
s.pop();
- Bu ifade Stack'in tepesindeki elemani siler ve o elemanin referansini döndürür. Eger elaman yoksa EmptyStackException olusturur.
s. peek();
- Bu ifade de . Stack'in tepesindeki elemana bir bir referans döndürür. Bu metodun pop'dan farki referans döndürdügü elemani silmemesidir.
s.empty();
- Bu metod Stack'in bos olum olmadigini sorgulamak için kullanilir.
int result = s.search( searchKey );
Yukaridaki ifade searchKey ile girilen elemanin Stack'da olup olmadigini sorgular. Eger eleman Stack'da ise result degerine indexi aktarilir. Eger eleman Stack'da yoksa result'a -1 atanir.
Stack class'i Vector class'ini inherit etmektedir. Bu nedenle de Enumeration özelligi her ikisinde de kullanilabilmektdir.
Dictionary Class'i
Bir Dictionary anahtarlari degerler döndürür. Dictionary abstract bir class'dir. Yani kendisinden bir instance üretilmez, sadece diger siniflara kaynak olur. Biraz sonra inceleyecek oldugumuz
Hashtable Class'i bu Dictionary Class'ini kullanmaktadir. Bu class size, isEmpty, get, put, ve remove gibi metodlari saglamaktadir. Ayrica iki farkli Enumeration yapilabilmektedir.
Bunlardan biri key'ler ile enumerate etmek digeri ise degerler ile enumerate etmektir.
0 Yorum Yapıldı