Java for Beginner
675 subscribers
554 photos
156 videos
12 files
845 links
Канал от новичков для новичков!
Изучайте Java вместе с нами!
Здесь мы обмениваемся опытом и постоянно изучаем что-то новое!

Наш YouTube канал - https://www.youtube.com/@Java_Beginner-Dev

Наш канал на RUTube - https://rutube.ru/channel/37896292/
Download Telegram
LinkedTransferQueue, особенности и внутреннее устройство

LinkedTransferQueue — это неблокирующая очередь с дополнительными функциями для передачи данных, основанная на алгоритмах немедленной передачи данных между потоками. Эта очередь является частью пакета java.util.concurrent и предоставляет высокопроизводительную реализацию интерфейса TransferQueue, который является подинтерфейсом BlockingQueue.

Особенности LinkedTransferQueue

Неблокирующая реализация: Основана на неблокирующих алгоритмах, что позволяет избежать блокировок при выполнении операций вставки и извлечения, обеспечивая высокую производительность.
Поддержка передачи данных (transfer): Помимо стандартных операций добавления и удаления элементов,
LinkedTransferQueue поддерживает операцию передачи данных (transfer), которая блокируется до тех пор, пока элемент не будет получен другим потоком.
Высокая производительность в многопоточной среде: Благодаря неблокирующим алгоритмам,
LinkedTransferQueue обеспечивает высокую производительность и масштабируемость в многопоточных приложениях.
Упорядоченность: Очередь гарантирует упорядоченность элементов по принципу FIFO (First-In-First-Out).

Внутреннее устройство LinkedTransferQueue

Структура данных:
Основой очереди является односвязный список узлов, где каждый узел содержит элемент и ссылку на следующий узел.
Узлы могут быть двух типов: данные (data nodes) и запросы (request nodes). Узлы данных содержат элементы, а запросы — нет.


Алгоритмы и синхронизация:
Используется алгоритм CAS (Compare-And-Swap) для обеспечения атомарности операций и предотвращения блокировок.
При вставке элемента создается новый узел данных и пытается добавить его в конец очереди.
При извлечении элемента очередь ищет узел данных и удаляет его.


Операция передачи данных (transfer):
При вызове метода transfer, элемент добавляется в очередь и операция блокируется до тех пор, пока элемент не будет извлечен другим потоком.
Это достигается за счет специального состояния узлов и механизма ожидания/оповещения потоков.


Пример кода внутреннего устройства
import java.util.concurrent.LinkedTransferQueue;
import java.util.concurrent.TransferQueue;

public class LinkedTransferQueueExample {
public static void main(String[] args) {
TransferQueue<Integer> queue = new LinkedTransferQueue<>();

Thread producer = new Thread(() -> {
try {
System.out.println("Producer: Transferring element 1");
queue.transfer(1);
System.out.println("Producer: Element 1 transferred");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});

Thread consumer = new Thread(() -> {
try {
System.out.println("Consumer: Waiting to take element");
Integer element = queue.take();
System.out.println("Consumer: Taken element " + element);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});

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


Ссылки на полезные статьи (спасибо авторам за проделанную работу) :
https://www.baeldung.com/java-transfer-queue
https://for-each.dev/lessons/b/-java-transfer-queue/

#Java #Training #Medium #LinkedTransferQueue
Основные методы LinkedTransferQueue и примеры использования

put(E e):

Вставляет элемент в очередь. Этот метод никогда не блокируется в LinkedTransferQueue, так как очередь не имеет ограничений на размер.
TransferQueue<Integer> queue = new LinkedTransferQueue<>();
queue.put(1); // Вставка элемента в очередь


offer(E e):

Вставляет элемент в очередь, возвращает true, если элемент был успешно вставлен.
boolean success = queue.offer(2); // Вставка элемента, возвращает true


transfer(E e):

Вставляет элемент в очередь и блокируется до тех пор, пока элемент не будет извлечен другим потоком.
queue.transfer(3); // Вставка элемента и блокировка до его извлечения


tryTransfer(E e):

Пытается вставить элемент в очередь, не блокируя, если нет ожидающего потребителя. Возвращает true, если элемент был передан.
boolean transferred = queue.tryTransfer(4); // Пытается передать элемент, не блокируя


tryTransfer(E e, long timeout, TimeUnit unit):

Пытается передать элемент, блокируясь в течение указанного времени ожидания, если нет готового потребителя. Возвращает true, если элемент был передан.
boolean transferredWithTimeout = queue.tryTransfer(5, 1, TimeUnit.SECONDS); // Пытается передать элемент с тайм-аутом


take():

Извлекает и удаляет элемент из головы очереди, блокируясь до тех пор, пока элемент не станет доступен.
Integer element = queue.take(); // Блокирующее извлечение элемента


poll(long timeout, TimeUnit unit):

Пытается извлечь элемент из головы очереди, блокируясь в течение указанного времени ожидания. Возвращает элемент или null, если тайм-аут истек.
Integer polledElement = queue.poll(1, TimeUnit.SECONDS); // Пытается извлечь элемент с тайм-аутом


remainingCapacity():

Возвращает оставшуюся емкость очереди. Для LinkedTransferQueue всегда возвращает Integer.MAX_VALUE.
int capacity = queue.remainingCapacity(); // Возвращает Integer.MAX_VALUE


hasWaitingConsumer():

Проверяет, есть ли ожидающие потребители.
boolean hasConsumers = queue.hasWaitingConsumer(); // Проверяет наличие ожидающих потребителей


getWaitingConsumerCount():

Возвращает количество ожидающих потребителей.
int consumerCount = queue.getWaitingConsumerCount(); // Возвращает количество ожидающих потребителей


Примеры использования LinkedTransferQueue

Производитель-потребитель с передачей данных:
import java.util.concurrent.LinkedTransferQueue;
import java.util.concurrent.TransferQueue;

public class ProducerConsumerExample {
public static void main(String[] args) {
TransferQueue<Integer> queue = new LinkedTransferQueue<>();

Thread producer = new Thread(() -> {
try {
for (int i = 0; i < 5; i++) {
System.out.println("Produced: " + i);
queue.transfer(i);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});

Thread consumer = new Thread(() -> {
try {
for (int i = 0; i < 5; i++) {
Integer item = queue.take();
System.out.println("Consumed: " + item);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});

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


#Java #Training #Medium #LinkedTransferQueue
Пример использования методов tryTransfer и poll с тайм-аутами.
import java.util.concurrent.LinkedTransferQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TransferQueue;

public class TimeoutExample {
public static void main(String[] args) {
TransferQueue<Integer> queue = new LinkedTransferQueue<>();

new Thread(() -> {
try {
boolean transferred = queue.tryTransfer(1, 1, TimeUnit.SECONDS);
if (transferred) {
System.out.println("Element transferred");
} else {
System.out.println("Failed to transfer element");
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}).start();

new Thread(() -> {
try {
Integer element = queue.poll(2, TimeUnit.SECONDS);
if (element != null) {
System.out.println("Element retrieved: " + element);
} else {
System.out.println("No element retrieved");
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}).start();
}
}


Использование
LinkedTransferQueue для синхронизации потоков, обеспечивая передачу сигналов между ними.
import java.util.concurrent.LinkedTransferQueue;
import java.util.concurrent.TransferQueue;

public class ThreadSyncExample {
public static void main(String[] args) {
TransferQueue<String> queue = new LinkedTransferQueue<>();

Thread thread1 = new Thread(() -> {
try {
queue.transfer("Signal from Thread 1");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});

Thread thread2 = new Thread(() -> {
try {
String signal = queue.take();
System.out.println("Received: " + signal);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});

thread1.start();
thread2.start();
}
}


#Java #Training #Medium #LinkedTransferQueue