Engellenmeyen Kuyruklar

Bağlantılı düğümlerde iş parçacığı açısından güvenli ve en önemlisi engellemeyen Kuyruk uygulamaları.

ConcurrentLinkedQueue<E> - çöp toplayıcıyla çalışmak üzere uyarlanmış beklemesiz bir algoritma kullanır. Bu algoritma, CAS üzerine kurulu olduğu için oldukça verimli ve çok hızlıdır. size() yöntemiuzun süre çalışabilir, bu yüzden her zaman çekmemek en iyisidir.

ConcurrentLinkedDeque<E> - Deque, Çift uçlu sıra anlamına gelir. Bu, verilerin her iki taraftan eklenebileceği ve alınabileceği anlamına gelir. Buna göre, sınıf her iki çalışma modunu da destekler: FIFO (İlk Giren İlk Çıkar) ve LIFO (Son Giren İlk Çıkar).

Uygulamada, ConcurrentLinkedDeque , LIFO kesinlikle gerekliyse kullanılmalıdır, çünkü düğümlerin çift yönlü olması nedeniyle bu sınıf, ConcurrentLinkedQueue ile karşılaştırıldığında performansta yarı yarıya kaybeder .

import java.util.concurrent.ConcurrentLinkedQueue;

public class  ConcurrentLinkedQueueExample {
   public static void main(String[] args) {
       ConcurrentLinkedQueue<String> queue = new ConcurrentLinkedQueue<>();

       Thread producer = new Thread(new Producer(queue));
       Thread consumer = new Thread(new Consumer(queue));

       producer.start();
       consumer.start();
   }
}

class Producer implements Runnable {

   ConcurrentLinkedQueue<String> queue;
   Producer(ConcurrentLinkedQueue<String> queue){
       this.queue = queue;
   }
   public void run() {
       System.out.println("Class for adding items to the queue");
       try {
           for (int i = 1; i < 5; i++) {
               queue.add("Item #" + i);
               System.out.println("Added: Item #" + i);
               Thread.sleep(300);
           }
       } catch (InterruptedException ex) {
           ex.printStackTrace();
           Thread.currentThread().interrupt();
       }
   }
}

class Consumer implements Runnable {

   ConcurrentLinkedQueue<String> queue;
   Consumer(ConcurrentLinkedQueue<String> queue){
       this.queue = queue;
   }

   public void run() {
       String str;
       System.out.println("Class for getting items from the queue");
       for (int x = 0; x < 5; x++) {
           while ((str = queue.poll()) != null) {
               System.out.println("Pulled out: " + str);
           }
           try {
               Thread.sleep(600);
           } catch (InterruptedException ex) {
               ex.printStackTrace();
               Thread.currentThread().interrupt();
           }
       }
   }
}

Kuyrukları Engelleme

BlockingQueue<E> arayüzü - çok fazla veri varsa, ConcurrentLinkedQueue yeterli değildir.

İş parçacıkları işlerini yapmakta başarısız olduğunda, kolayca bir OutOfMemmoryException alabilirsiniz . Ve bu tür durumların ortaya çıkmaması için, kuyruk ve koşullu kilitlerle doldurmak ve çalışmak için farklı yöntemlerin varlığıyla çalışmak için bir BlockingQueue'muz var.

BlockingQueue boş öğeleri tanımaz veböyle bir öğe eklemeye veya almaya çalışırken bir NullPointerException oluşturur. Zaman aşımı süresi içinde kuyruğa hiçbir öğe yerleştirilmemişse, anket yöntemi boş bir öğe döndürür.

BlockingQueue<E> Uygulamaları

BlockingQueue uygulamalarımızın her birine daha yakından bakalım :

ArrayBlockingQueue<E>, klasik halka arabelleği üzerine kurulmuş bir engelleme kuyruğu sınıfıdır. Burada kilitlerin “dürüstlüğünü” yönetme fırsatımız var. adil=yanlış (varsayılan) ise, iş parçacığı sıralaması garanti edilmez.

DelayQueue<E extensions Delayed>, her öğede Delayed arabiriminin getDelay yöntemi aracılığıyla tanımlanan belirli bir gecikmeden sonra öğeleri sıradan çekmenize izin veren bir sınıftır.

LinkedBlockingQueue<E>, "iki kilit sırası" algoritmasında uygulanan bağlantılı düğümlerde bir engelleme sırasıdır: ilk kilit ekleme içindir, ikincisi sıradan bir öğe çekmek içindir. ArrayBlockingQueue ile karşılaştırıldığında kilitler nedeniyle, bu sınıf yüksek performansa sahiptir, ancak daha fazla bellek gerektirir. Kuyruk boyutu yapıcı aracılığıyla ayarlanır ve varsayılan olarak Integer.MAX_VALUE'ye eşittir.

PriorityBlockingQueue<E>, PriorityQueue üzerinde çok iş parçacıklı bir sarıcıdır. Karşılaştırıcı, öğenin ekleneceği mantıktan sorumludur. En küçük eleman önce çıkar.

SynchronousQueue<E> - kuyruk, FIFO (ilk giren ilk çıkar) ilkesine göre çalışır. Her ekleme işlemi, "Tüketici" iş parçacığı öğeyi sıradan çekene kadar "Üretici" iş parçacığını bloke eder ve bunun tersi, "Tüketici", "Üretici" öğeyi ekleyene kadar bekler.

BlockingDeque<E>, çift yönlü engelleme sırası için ek yöntemleri açıklayan bir arabirimdir. Veriler, kuyruğun her iki tarafından da eklenebilir ve çıkarılabilir.

LinkedBlockingDeque<E>, tek kilitli basit bir çift yönlü liste olarak uygulanan, bağlantılı düğümlerde çift yönlü bir engelleme sırasıdır. Kuyruk boyutu yapıcı aracılığıyla ayarlanır ve varsayılan olarak Integer.MAX_VALUE'ye eşittir.

TransferQueue<E> - arayüz ilginçtir, çünkü kuyruğa bir öğe eklendiğinde, başka bir Tüketici iş parçacığı öğeyi sıradan çekenekadar Üretici iş parçacığının eklenmesini engellemek mümkündürAyrıca belirli bir zaman aşımı için bir kontrol ekleyebilir veya bekleyen Tüketiciler için bir kontrol ayarlayabilirsiniz . Sonuç olarak, eşzamansız ve eşzamanlı mesajları destekleyen bir veri aktarım mekanizması elde ederiz.

LinkedTransferQueue<E>, Slack algoritmasına sahip Dual Queues tabanlı bir TransferQueue uygulamasıdırBoştayken CAS'ı (yukarıya bakın) ve iplik parkını yoğun bir şekilde kullanır.