bu

"Merhaba, Amigo!"

"Bekle-bildir ile ilgili olarak sizinle derinlere inmek istiyorum. Bekle-bildir yöntemleri, ileti dizilerinin etkileşime girmesi için uygun bir mekanizma sağlar. Ayrıca, ileti dizisi etkileşimi için karmaşık üst düzey mekanizmalar oluşturmak için de kullanılabilirler."

"Küçük bir örnekle başlayacağım. Diyelim ki, bir web sitesi aracılığıyla kullanıcılar tarafından oluşturulan çeşitli görevleri gerçekleştirmesi gereken bir sunucu programımız var. Kullanıcılar farklı zamanlarda çeşitli görevler ekleyebilir. Görevler yoğun kaynak gerektirir, ancak sunucumuzun 8 -core işlemci başa çıkabilir.Sunucudaki görevleri nasıl gerçekleştirmeliyiz?"

"Öncelikle, işlemci çekirdeği sayısı kadar çalışan iş parçacığı grubu oluşturacağız. Her iş parçacığı kendi çekirdeğinde çalışabilecek: İş parçacıkları birbirine müdahale etmeyecek ve işlemci çekirdekleri çalışmayacaktır. boş durmak."

"İkincisi, kullanıcıların görevlerinin ekleneceği bir kuyruk nesnesi oluşturacağız. Farklı türdeki görevler, farklı nesnelere karşılık gelecek, ancak çalıştırılabilmesi için hepsi Runnable arayüzünü uygulayacak."

"Bana bir görev nesnesi örneği verebilir misiniz?"

"Buna bir bak:"

run() yöntemi çağrıldığında n faktöriyelini hesaplayan bir sınıf
class Factorial implements Runnable
{
 public int n = 0;
 public long result = 1;

 public Factorial (int n)
 {
  this.n = n;
 }

 public void run()
 {
  for (int i = 2; i <= n; i++)
   result *= i;
 }
}

"Şimdiye kadar, çok iyi."

"Harika. O zaman bir kuyruk nesnesinin nasıl görünmesi gerektiğini inceleyelim. Bana onun hakkında ne söyleyebilirsin?"

"İş parçacığı açısından güvenli olmalıdır. Görev nesneleri, onları kullanıcılardan alan bir iş parçacığı tarafından yüklenir ve ardından görevler çalışan iş parçacıkları tarafından alınır."

"Evet. Ya bir süreliğine görevlerimiz biterse?"

"O zaman çalışan iş parçacıkları daha fazlası olana kadar beklemeli."

"Doğru. Şimdi tüm bunların tek bir kuyrukta oluşturulabileceğini hayal edin. Şuna bakın:"

Bir görev kuyruğu. Görev yoksa, iş parçacığı uykuya dalar ve birinin görünmesini bekler:
public class JobQueue
{
 ArrayList jobs = new ArrayList();

 public synchronized void put(Runnable job)
 {
  jobs.add(job);
  this.notifyAll();
 }

 public synchronized Runnable getJob()
 {
  while (jobs.size() == 0)
   this.wait();

  return jobs.remove(0);
 }
}

"Görev listesinin boş olup olmadığını kontrol eden bir getJob yöntemimiz var . Ardından iş parçacığı, listede bir şey görünene kadar uyku moduna geçer (bekler).

"Listeye yeni bir görev eklemenizi sağlayan put yöntemi de var . Yeni bir görev eklenir eklenmez, notifyAll yöntemi çağrılır. Bu yöntemin çağrılması, getJob yöntemi içinde uykuya dalmış tüm çalışan iş parçacıklarını uyandırır."

"Bekle ve bildir yöntemlerinin nasıl çalıştığını tekrar hatırlayabiliyor musun?"

"Bekleme yöntemi yalnızca senkronize bir blok içinde, bir muteks nesnesinde çağrılır. Bizim durumumuzda: bu. Ayrıca, iki şey olur:

1) İplik uykuya dalar.

2) İş parçacığı muteksi geçici olarak serbest bırakır (uyanana kadar).

"Bundan sonra, diğer iş parçacıkları senkronize bloğa girebilir ve aynı muteksi alabilir."

" notifyAll yöntemi, yalnızca bir muteks nesnesinin senkronize edilmiş bloğu içinde de çağrılabilir. Bizim durumumuzda: bu. Ayrıca, iki şey olur:"

1) Bu mutex nesnesinde bekleyen tüm threadler uyandırılır.

2) Mevcut thread senkronize bloktan çıktıktan sonra, uyanmış threadlerden biri muteksi alır ve işine devam eder. Muteksi serbest bıraktığında, başka bir uyanmış iş parçacığı muteksi alır, vb.

"Otobüse çok benziyor. İçeri giriyorsun ücretini ödemek istiyorsun ama şoför yok. Yani 'uyuyakalıyorsun'. En sonunda otobüs tıklım tıklım ama yine de ücreti verecek kimse yok. Sonra şoför gelir ve "Ücret, lütfen" der. Ve bu, ... "

"İlginç bir karşılaştırma. Ama otobüs nedir?"

"Julio bunu açıkladı. 21. yüzyılda kullanılan bu tuhaf şeyler vardı."