Java MultiThreading (İki Thread Arası Senkronizasyon)

Batuhan Düzgün tarafından yayınlanmıştır 10. April 2012 09:09
  
Merhaba arkadaşlar biliyorum uzun zamandır yine makale yazamadım. Malesef ki iş yoğunluğu yüzünden ve ekstra işler nedeniyle blogu biraz boşladım hepinizden özür dilerim. En nihayet bir fırsat bulup edindiğim yeni tecrübe ve bilgileri sizlerle paylaşma adına ilerleyen günlerde ilginç konularda güzel yazılar hazırlayacağıma inanıyorum. Bu yazı konusu ise son zamanlarda epeyce bir tecrübe edindiğimi düşündüğüm MultiThreading hakkında olacaktır. 
 
MultiThreading Nedir ?
 
Özellikle Bilgisayar Mühendisliği öğrencileri aldıkları İşletim Sistemleri dersinden ötürü bu konuyu sıkça duymuşlardır. MultiThreading sözlük anlamıyla "Çok Kanallı" şeklindedir. Yani bilgisayar ortamında iki işlemin paralel olarak yürütülmesi işlemidir. Tabi buradaki paralellik yazılımsal olarak mevcuttur. Özellikle tek çekirdekli işlemcilerde MultiThreading iki işlemin ardı sıra çalıştırılmasıyla olur. Fakat bu çok hızlı gerçeleştirildiği için sanki biz bilgisayarı kullanırken her iki işide paralel olarak eş zamanlı yapıyormuş hissine kapılırız. Mesela Word'de yazı yazarken media playerda müzik dinlemek son kullanıcı açısından paralel iki iştir fakat işlemci çerçevesinden bakıldığında bu iki işlem parçası ardı ardına işletilerek yapılır.
 
İşte günümüzdeki birçok üst düzey programlama dili MultiThreading desteğini vermektedir. Bu nedenle biz yazılım mühendisleride bu destek sayesinde çok kanallı olarak işlemleri yapabilmekteyiz. Fakat, şu yanlış kanıdan kaçınalım. Ne kadar çok Thread açarsam verim ve hız o kadar artar diye ümitlenmeyiniz. Belli bir Thread sayısından sonra hızda ve verimde bir arış göremezsiniz. O doyum noktasına ulaşıldığında Thread sayısını istediğiniz kadar artırsanızda bir fayda elde edemeyeceksiniz. Ayrıca unutmayınız ki işlemci açısından bir Thread yaratmak oldukça masraflı bir iştir.
 
Yazıdaki Thread Örneğinin İçeriği Nedir ?
 
Bu yazıdaki hazırlamış olduğum MultiThreading örneği basit ve anlaşılır bir örnek düzeyindedir. Kısaca şöyle açıklanabilir. Dosyaya yazma işlemi yapacak olan iki ayrı Thread yaratılacaktır. Herhangi bir Thread'den biri dosyaya yazma işlemi yaparken diğeri beklemeye girecektir. İkisi aynı dosyayı ortak bi şekilde kullanacaktır.
  
Şimdi Eclipse IDE 'de yeni bir Java Projesi oluşturulur. Ardından aşağıdaki gibi her Thread için Runnable interface'den kalıtım alan özel sınıflar yazılır. 
  
Aşağıdaki gibi "main"  metodu içeren bir sınıf hazırlanır. 
 
 
 
 
Daha sonra projeye sağ tıklanıp, "Run As" >> "Run Configurations"  yolu takip edilerek  aşağıdaki gibi Java uygulaması için bir Application yaratılır.
 
 
 
Daha sonra aşağıdaki gibi sınıflar yazılır.
 
Runnable1.java Sınıfı ...
 

public class Runnable1 implements Runnable {

// Senkronize edilecek olan Thread referansını tutar.
private Runnable2 crossRunnable = null;
private boolean threadLoop = true;
// Diğer Thread tarafından dosyaya yazma işlemi yapılırken bekletme işlemini yapacak olan nesnedir.
private Object waitObject = null;
private int counter = 0;
// Diğer çapraz bağlanmış Thread dosyaya yazıyorsa bu sınıfa beklemesini söyler. Bu değişkeni true yapar.
public boolean isWait = false;
public Runnable1() {
waitObject = new Object();
}
public void setCrossRunnable(Runnable2 runn) {
crossRunnable = runn;
}
// Beklemede olan nesneyi uyarır ve Thread kaldığı yerden çalışmaya devam eder.
public void notifyObject() {
synchronized (waitObject) {
isWait = false;
waitObject.notifyAll();
}
}  
// Thread sonlandırılır.
public void stopThread() {
threadLoop = false;
}
@Override
public void run() {
while(threadLoop) {
synchronized (waitObject) {
if(isWait) {
try {
System.out.println("Thr1 beklemede.");
// Beklemeye girdiği andır.
waitObject.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
// Beklemeden çıktığında Dosyaya yazma erişimi bu Thread'e ait olur.
// Diğer Thread'i beklemesi için uyarır.
crossRunnable.isWait = true;
FileOperation.writeMessageToFile("Thread1 sayac : " + counter, true);
crossRunnable.notifyObject();
counter++;
}
}
}
 
Runnable2.java Sınıfı ... 
 
public class Runnable2 implements Runnable {

// Senkronize edilecek olan Thread referansını tutar.
private Runnable1 crossRunnable;
private boolean threadLoop = true;
// Diğer Thread tarafından dosyaya yazma işlemi yapılırken bekletme işlemini yapacak olan nesnedir.
private Object waitObject = null;
private int counter = 0;
// Diğer çapraz bağlanmış Thread dosyaya yazıyorsa bu sınıfa beklemesini söyler. Bu değişkeni true yapar.
public boolean isWait = true;
public Runnable2() {
waitObject = new Object();
}
public void setCrossRunnable(Runnable1 runn) {
crossRunnable = runn;
}
// Beklemede olan nesneyi uyarır ve Thread kaldığı yerden çalışmaya devam eder.
public void notifyObject() {
synchronized (waitObject) {
isWait = false;
waitObject.notifyAll();
}
// Thread sonlandırılır.
public void stopThread() {
threadLoop = false;
}
@Override
public void run() {
while(threadLoop) {
synchronized (waitObject) {
if(isWait) {
try {
System.out.println("Thr2 beklemede.");
// Beklemeye girdiği andır.
waitObject.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
// Beklemeden çıktığında Dosyaya yazma erişimi bu Thread'e ait olur.
// Diğer Thread'i beklemesi için uyarır.
crossRunnable.isWait = true;
FileOperation.writeMessageToFile("Thread2 sayac : " + counter, false);
crossRunnable.notifyObject();
counter++;
}
}
}
 
Dosya işelmlerini yerine getirecek olan sınıf aşağıdaki gibi kodlanmıştır.
 
 
FileOperation.java Sınıfı ...
 
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;


public class FileOperation {

private static String path = "D:\\deneme.txt";
private static FileWriter fstream;
private static PrintWriter  out;
// Dosyaya mesajı yazan metoddur.
public static void writeMessageToFile(String message, boolean value) {
try {
// Gün ve mesaj bilgisini string şeklinde hazırlanır.
String messageText = (new Date()).toString() + "\t" + message;
File file = new File(path);
// deneme.txt adından bir dosya olup olmadığı kontrol edilir.
if(!file.exists()) {
// Yoksa yeni birtane yaratılır.
file.createNewFile();
}
// Dosya true değeri ile append şeklinde açılır.
fstream = new FileWriter(file, true);
out = new PrintWriter(fstream);
// Dosyaya veri yazılır.
out.println(messageText);
out.close();
fstream.close();
// Birinci Thread ise 45 milisaniye , ikinci Thread ise 15 milisaniye uyutulur
if(value) {
Thread.sleep(45);
} else {
Thread.sleep(15);
}
} catch (Exception e) {
out.close();
try {
fstream.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
fstream = null;
out = null;
}
}
 
mainClass.java Sınıfı ...
 
Bu sınıf içindeki main metodundan itibaren program çalışmaya başlar.

/**
 * @Batuhan Düzgün Figensoft
 *
 */
public class mainClass {

/**
* @param args
*/
public static void main(String[] args) {
// Her iki Thread yaratılır ve çapraz olarak birbirine bağlanır.
Runnable1 runn1 = new Runnable1();
Thread thread1 = new Thread(runn1);
Runnable2 runn2 = new Runnable2();
Thread thread2 = new Thread(runn2);
runn1.setCrossRunnable(runn2);
runn2.setCrossRunnable(runn1);
thread1.start();
thread2.start();
try {
// 45 saniye işletildikten sonra threadler sonlandırılır.
Thread.sleep(45000);
runn1.stopThread();
runn2.stopThread();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
 
 
Programı çalıştırdıktan sonra aşağıdaki ekran görüntülerini almanız gerekmektedir.
 
 
 
Ardından dosyayı kontrol edelim. Dosya boyutu 91 kb şeklinde oldu. Aşağıdaki gibi dosya içeriğinden bir görüntü alınmıştır.
 
 
 
Umarım zevkle okuyacağınız bir makale olmuştur. Bir sonraki makalemde görüşmek dileğiyle ...
 
Batuhan Düzgün
 
Bilgisayar Mühendisi
Endüstri Mühendisi
Figensoft Yazılım Mühendisi 

Currently rated 5.0 by 1 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Etiketler:

Java

Comments

Add comment


(Will show your Gravatar icon)  

  Country flag

biuquote
  • Comment
  • Preview
Loading





Bu site BlogEngine.NET 1.4.5.0 ile oluşturulmuştur. Türkçe çevirisi BlogEngine TR ekibi tarafından yapılmıştır.

Batuhan Düzgün

Sakarya Üniversitesi 

Bilgisayar Mühendisi

Endüstri Mühendisi

Yeditepe Üniversitesi

Bilgisayar Mühendisliği Yüksek Lisans 

 sahibinden.com

   Kıdemli Uzman Yazılım Mühendisi  

E-Mail 

   batuhan.duzgun@sahibinden.com

   batuhan.duzgun@windowslive.com

  github.com/batux

 

Sayfalar

Calendar

<<  September 2018  >>
MoTuWeThFrSaSu
272829303112
3456789
10111213141516
17181920212223
24252627282930
1234567

Yazıları geniş takvimde göster