Java - Çoklu okuma

Java, çok iş parçacıklı bir programlama dilidir , yani Java kullanarak çok iş parçacıklı program geliştirebiliriz. Çok iş parçacıklı bir program, eşzamanlı olarak çalışabilen iki veya daha fazla parça içerir ve her bir parça, aynı anda farklı bir görevi yerine getirerek, bilgisayarınızda birden çok CPU'ya sahip olduğunda mevcut kaynakların en iyi şekilde kullanılmasını sağlayabilir.

Tanım olarak, çoklu görev, birden çok işlemin bir CPU gibi ortak işlem kaynaklarını paylaşmasıdır. Çoklu iş parçacığı, çoklu görev fikrini, tek bir uygulama içindeki belirli işlemleri ayrı iş parçacıklarına ayırabileceğiniz uygulamalara genişletir. İpliklerin her biri paralel çalışabilir. İşletim sistemi, işlem süresini yalnızca farklı uygulamalar arasında değil, aynı zamanda bir uygulama içindeki her iş parçacığı arasında da böler.

Çoklu iş parçacığı, aynı program içinde birden çok etkinliğin aynı anda ilerleyebileceği şekilde yazmanıza olanak tanır.

Bir İpliğin Yaşam Döngüsü

Bir iplik, yaşam döngüsünde çeşitli aşamalardan geçer. Örneğin, bir iplik doğar, başlar, çalışır ve sonra ölür. Aşağıdaki diyagram, bir dişin tüm yaşam döngüsünü göstermektedir.

Aşağıdakiler yaşam döngüsünün aşamalarıdır -

  • New- Yeni bir iş parçacığı, yeni durumda yaşam döngüsüne başlar. Program iş parçacığını başlatana kadar bu durumda kalır. Aynı zamanda birborn thread.

  • Runnable- Yeni doğan bir iplik başladıktan sonra, iplik çalıştırılabilir hale gelir. Bu durumdaki bir iş parçacığının görevini yürüttüğü kabul edilir.

  • Waiting- Bazen, iş parçacığı başka bir iş parçacığının bir görevi gerçekleştirmesini beklerken, bir iş parçacığı bekleme durumuna geçiş yapar. Bir iş parçacığı, yalnızca başka bir iş parçacığı beklemede iş parçacığını yürütmeye devam etmesi için sinyal verdiğinde çalıştırılabilir duruma geri döner.

  • Timed Waiting- Çalıştırılabilir bir iş parçacığı, belirli bir zaman aralığı için zamanlı bekleme durumuna girebilir. Bu durumdaki bir iş parçacığı, bu zaman aralığı sona erdiğinde veya beklediği olay meydana geldiğinde çalıştırılabilir duruma geri döner.

  • Terminated (Dead) - Çalıştırılabilir bir iş parçacığı, görevini tamamladığında veya başka şekilde sona erdiğinde sonlandırılmış duruma girer.

Konu Öncelikleri

Her Java iş parçacığının, işletim sisteminin iş parçacıklarının zamanlanacağı sırayı belirlemesine yardımcı olan bir önceliği vardır.

Java iş parçacığı öncelikleri MIN_PRIORITY (1 sabit) ve MAX_PRIORITY (10 sabit) arasındadır. Varsayılan olarak, her iş parçacığına NORM_PRIORITY (5 sabit) önceliği verilir.

Daha yüksek önceliğe sahip iş parçacıkları bir program için daha önemlidir ve daha düşük öncelikli iş parçacıklarından önce işlemci süresi tahsis edilmelidir. Bununla birlikte, iş parçacığı öncelikleri iş parçacıklarının çalıştırılma sırasını garanti edemez ve büyük ölçüde platforma bağlıdır.

Çalıştırılabilir Bir Arayüz Uygulayarak Bir İş Parçacığı Oluşturun

Sınıfınızın bir iş parçacığı olarak çalıştırılması amaçlanıyorsa, bunu bir Runnablearayüz. Üç temel adımı izlemeniz gerekecek -

Aşama 1

İlk adım olarak, bir tarafından sağlanan run () yöntemini uygulamanız gerekir. Runnablearayüz. Bu yöntem iş parçacığı için bir giriş noktası sağlar ve tüm iş mantığınızı bu yöntemin içine koyarsınız. Aşağıda, run () yönteminin basit bir sözdizimi verilmiştir -

public void run( )

Adım 2

İkinci bir adım olarak, bir Thread aşağıdaki yapıcıyı kullanan nesne -

Thread(Runnable threadObj, String threadName);

Nerede, threadObj bir sınıfın bir örneği olup bu uygularRunnable arayüz ve threadName yeni konuya verilen isimdir.

Aşama 3

Bir Thread nesnesi oluşturulduktan sonra, onu arayarak başlatabilirsiniz. start()run () yöntemine bir çağrı yürüten yöntem. Aşağıda start () yönteminin basit bir sözdizimi verilmiştir -

void start();

Misal

İşte yeni bir iş parçacığı oluşturan ve onu çalıştırmaya başlayan bir örnek -

class RunnableDemo implements Runnable {
   private Thread t;
   private String threadName;
   
   RunnableDemo( String name) {
      threadName = name;
      System.out.println("Creating " +  threadName );
   }
   
   public void run() {
      System.out.println("Running " +  threadName );
      try {
         for(int i = 4; i > 0; i--) {
            System.out.println("Thread: " + threadName + ", " + i);
            // Let the thread sleep for a while.
            Thread.sleep(50);
         }
      } catch (InterruptedException e) {
         System.out.println("Thread " +  threadName + " interrupted.");
      }
      System.out.println("Thread " +  threadName + " exiting.");
   }
   
   public void start () {
      System.out.println("Starting " +  threadName );
      if (t == null) {
         t = new Thread (this, threadName);
         t.start ();
      }
   }
}

public class TestThread {

   public static void main(String args[]) {
      RunnableDemo R1 = new RunnableDemo( "Thread-1");
      R1.start();
      
      RunnableDemo R2 = new RunnableDemo( "Thread-2");
      R2.start();
   }   
}

Bu, aşağıdaki sonucu verecektir -

Çıktı

Creating Thread-1
Starting Thread-1
Creating Thread-2
Starting Thread-2
Running Thread-1
Thread: Thread-1, 4
Running Thread-2
Thread: Thread-2, 4
Thread: Thread-1, 3
Thread: Thread-2, 3
Thread: Thread-1, 2
Thread: Thread-2, 2
Thread: Thread-1, 1
Thread: Thread-2, 1
Thread Thread-1 exiting.
Thread Thread-2 exiting.

Bir İş Parçacığı Sınıfını Genişleterek Bir İş Parçacığı Oluşturun

Bir iş parçacığı oluşturmanın ikinci yolu, genişleyen yeni bir sınıf oluşturmaktır. ThreadAşağıdaki iki basit adımı kullanarak sınıf. Bu yaklaşım, Thread sınıfındaki mevcut yöntemler kullanılarak oluşturulan birden çok iş parçacığının işlenmesinde daha fazla esneklik sağlar.

Aşama 1

Geçersiz kılmanız gerekecek run( )Thread sınıfında mevcut yöntem. Bu yöntem iş parçacığı için bir giriş noktası sağlar ve tüm iş mantığınızı bu yöntemin içine koyarsınız. Aşağıda, run () yönteminin basit bir sözdizimi verilmiştir -

public void run( )

Adım 2

Thread nesnesi oluşturulduktan sonra, onu arayarak başlatabilirsiniz. start()run () yöntemine bir çağrı yürüten yöntem. Aşağıda start () yönteminin basit bir sözdizimi verilmiştir -

void start( );

Misal

İşte İpliği uzatmak için yeniden yazılmış önceki program -

class ThreadDemo extends Thread {
   private Thread t;
   private String threadName;
   
   ThreadDemo( String name) {
      threadName = name;
      System.out.println("Creating " +  threadName );
   }
   
   public void run() {
      System.out.println("Running " +  threadName );
      try {
         for(int i = 4; i > 0; i--) {
            System.out.println("Thread: " + threadName + ", " + i);
            // Let the thread sleep for a while.
            Thread.sleep(50);
         }
      } catch (InterruptedException e) {
         System.out.println("Thread " +  threadName + " interrupted.");
      }
      System.out.println("Thread " +  threadName + " exiting.");
   }
   
   public void start () {
      System.out.println("Starting " +  threadName );
      if (t == null) {
         t = new Thread (this, threadName);
         t.start ();
      }
   }
}

public class TestThread {

   public static void main(String args[]) {
      ThreadDemo T1 = new ThreadDemo( "Thread-1");
      T1.start();
      
      ThreadDemo T2 = new ThreadDemo( "Thread-2");
      T2.start();
   }   
}

Bu, aşağıdaki sonucu verecektir -

Çıktı

Creating Thread-1
Starting Thread-1
Creating Thread-2
Starting Thread-2
Running Thread-1
Thread: Thread-1, 4
Running Thread-2
Thread: Thread-2, 4
Thread: Thread-1, 3
Thread: Thread-2, 3
Thread: Thread-1, 2
Thread: Thread-2, 2
Thread: Thread-1, 1
Thread: Thread-2, 1
Thread Thread-1 exiting.
Thread Thread-2 exiting.

Konu Yöntemleri

Aşağıda, Thread sınıfında bulunan önemli yöntemlerin listesi bulunmaktadır.

Sr.No. Yöntem ve Açıklama
1

public void start()

İş parçacığını ayrı bir yürütme yolunda başlatır, ardından bu Thread nesnesinde run () yöntemini çağırır.

2

public void run()

Bu Thread nesnesi, ayrı bir Runnable hedefi kullanılarak başlatılmışsa, bu Runnable nesnesinde run () yöntemi çağrılır.

3

public final void setName(String name)

Thread nesnesinin adını değiştirir. Adı almak için bir getName () yöntemi de vardır.

4

public final void setPriority(int priority)

Bu Thread nesnesinin önceliğini ayarlar. Olası değerler 1 ile 10 arasındadır.

5

public final void setDaemon(boolean on)

True parametresi, bu İş Parçacığını bir arka plan iş parçacığı olarak gösterir.

6

public final void join(long millisec)

Geçerli iş parçacığı bu yöntemi ikinci bir iş parçacığı üzerinde çağırır ve mevcut iş parçacığının ikinci iş parçacığı sona erene veya belirtilen milisaniye sayısı geçene kadar engellenmesine neden olur.

7

public void interrupt()

Bu iş parçacığını keserek herhangi bir nedenle engellenmişse yürütmeye devam etmesine neden olur.

8

public final boolean isAlive()

İş parçacığı canlıysa doğru döndürür; bu, iş parçacığı başlatıldıktan sonra ancak tamamlanmadan önce çalıştırılır.

Önceki yöntemler, belirli bir Thread nesnesinde çağrılır. Thread sınıfındaki aşağıdaki yöntemler statiktir. Statik yöntemlerden birini çağırmak, şu anda çalışan iş parçacığı üzerinde işlemi gerçekleştirir.

Sr.No. Yöntem ve Açıklama
1

public static void yield()

Şu anda çalışan iş parçacığının planlanmayı bekleyen aynı önceliğe sahip diğer tüm iş parçacıklarını vermesine neden olur.

2

public static void sleep(long millisec)

Şu anda çalışan iş parçacığının en azından belirtilen milisaniye kadar engellenmesine neden olur.

3

public static boolean holdsLock(Object x)

Mevcut iş parçacığı verilen Nesnede kilidi tutuyorsa doğru döndürür.

4

public static Thread currentThread()

Bu yöntemi çağıran iş parçacığı olan şu anda çalışan iş parçacığına bir başvuru döndürür.

5

public static void dumpStack()

Çok iş parçacıklı bir uygulamada hata ayıklarken yararlı olan, şu anda çalışan iş parçacığı için yığın izlemeyi yazdırır.

Misal

Aşağıdaki ThreadClassDemo programı, Thread sınıfının bu yöntemlerinden bazılarını göstermektedir. Bir sınıf düşününDisplayMessage hangi uygular Runnable -

// File Name : DisplayMessage.java
// Create a thread to implement Runnable

public class DisplayMessage implements Runnable {
   private String message;
   
   public DisplayMessage(String message) {
      this.message = message;
   }
   
   public void run() {
      while(true) {
         System.out.println(message);
      }
   }
}

Aşağıda, Thread sınıfını genişleten başka bir sınıf var -

// File Name : GuessANumber.java
// Create a thread to extentd Thread

public class GuessANumber extends Thread {
   private int number;
   public GuessANumber(int number) {
      this.number = number;
   }
   
   public void run() {
      int counter = 0;
      int guess = 0;
      do {
         guess = (int) (Math.random() * 100 + 1);
         System.out.println(this.getName() + " guesses " + guess);
         counter++;
      } while(guess != number);
      System.out.println("** Correct!" + this.getName() + "in" + counter + "guesses.**");
   }
}

Aşağıda, yukarıda tanımlanan sınıfları kullanan ana program yer almaktadır -

// File Name : ThreadClassDemo.java
public class ThreadClassDemo {

   public static void main(String [] args) {
      Runnable hello = new DisplayMessage("Hello");
      Thread thread1 = new Thread(hello);
      thread1.setDaemon(true);
      thread1.setName("hello");
      System.out.println("Starting hello thread...");
      thread1.start();
      
      Runnable bye = new DisplayMessage("Goodbye");
      Thread thread2 = new Thread(bye);
      thread2.setPriority(Thread.MIN_PRIORITY);
      thread2.setDaemon(true);
      System.out.println("Starting goodbye thread...");
      thread2.start();

      System.out.println("Starting thread3...");
      Thread thread3 = new GuessANumber(27);
      thread3.start();
      try {
         thread3.join();
      } catch (InterruptedException e) {
         System.out.println("Thread interrupted.");
      }
      System.out.println("Starting thread4...");
      Thread thread4 = new GuessANumber(75);
      
      thread4.start();
      System.out.println("main() is ending...");
   }
}

Bu, aşağıdaki sonucu verecektir. Bu örneği tekrar tekrar deneyebilirsiniz ve her seferinde farklı bir sonuç alırsınız.

Çıktı

Starting hello thread...
Starting goodbye thread...
Hello
Hello
Hello
Hello
Hello
Hello
Goodbye
Goodbye
Goodbye
Goodbye
Goodbye
.......

Başlıca Java Çoklu Okuma Kavramları

Java'da Multithreading programlama yaparken, aşağıdaki kavramları çok kullanışlı bir şekilde kullanmanız gerekir -

  • İş parçacığı senkronizasyonu nedir?

  • Interthread iletişimi yönetme

  • İş parçacığı kilitlenmesinin ele alınması

  • Başlıca iş parçacığı işlemleri