JavaRush /Java Blog /Random EN /SynchronousQueue example in Java - solving the problem Pr...
profeg
Level 18

SynchronousQueue example in Java - solving the problem Producer Consumer

Published in the Random EN group
SynchronousQueue example in Java - solving the problem Producer Consumer
SynchronousQueue is a special type of BlockingQueue in which each insert operation must wait for a corresponding remove command in another thread, and vice versa. When you call the put() method on a SynchronousQueue, it blocks until another thread takes that element from it. Accordingly, if another thread tries to remove an element from it, and the element is not there, then that thread blocks until the other thread puts the element in the queue. You can think of SynchronousQueue as an athlete ( thread ) running with the Olympic torch, he runs with the torch (the object that is being passed on) and passes it to another athlete waiting on the other side. If you pay attention to the name, you will understand that SynchronousQueue is named so for a reason; it transfers data synchronously to another thread ; it waits for someone to pick up the data instead of just putting it in and exiting (an asynchronous operation). If you are familiar with CSP and Ada, then you know that synchronized queues are similar to the meeting of threads. They are well suited for control transfer constructs in which an object running in one thread must synchronize with an object in another thread in order to pass some information, event, or task to it. In previous multi-threaded programming tutorials, we learned how to solve the producer-consumer problem using the wait and notify and BlockingQueue methods . Now we will learn how to apply the producer-consumer pattern using SynchronousQueue. This class additionally supports fair behavior for ordering the waits of the producer and consumer threads. By default, this ordering is not guaranteed. However, queues created with fair properties guarantee access for threads in a FIFO (Firs In First Out) queue.
Producer/Consumer using SynchronousQueue in Java.
SynchronousQueue example in Java - solving the problem Producer Consumer - 1 As I said above, there is nothing better than the producer-consumer problem for understanding inter-thread communication in any programming language. In this problem, one thread acts as a producer that produces events and tasks, and the other thread acts as a consumer of it. A shared buffer is used to transfer data from producer to consumer. The difficulty of solving this problem comes in extreme cases, for example, when the manufacturer is forced to wait because... the buffer is full or the consumer is forced to wait because the buffer is empty. This was easily solved, because... The blocking queue provided not only a buffer for storing data, but also flow control, blocking the thread calling the put() method (Producer) if the buffer was full, and blocking the thread calling the take() method (Consumer) if the buffer was empty. Now we will solve this same problem using SynchronousQueue, a special kind of parallel collections with zero capacity. In the following example, we have two threads called PRODUCER and CONSUMER (always give names to threads, this is a very good style of multi-threaded programming). The first thread posts the score in the game, and the second thread consumes it. The score in the game is nothing more than an object of type String. But if you run the program with a different type, you won't notice any difference. To understand how SynchronousQueue works, and how to solve the producer-consumer problem, you need to: either run the program for debugging (debug) in the Eclipse environment , or simply start the producer thread by commenting out consumer.start(); if the consumer thread is not running then the producer thread will be blocked at queue.put(event); if running, you will not be able to see the producer [PRODUCER] publishing the :FOUR event. This happens because specific behavior of SynchronousQueue, which ensures that the thread posting data will block until another thread takes the data, and vice versa. You can test the rest of the code by commenting out producer.start(); and starting only the consumer thread. If you carefully study what the program outputs, you will notice that the order of output is reversed. It looks like the [CONSUMER] thread took the data before the [PRODUCER] thread produced it. This is because SynchronousQueue does not guarantee queueing by default. But it has fairness rules that set access to threads in FIFO order. You can enable these rules by passing true to the overloaded SynchronousQueue constructor like this: import java.util.concurrent.SynchronousQueue; /** * Java Program to solve Producer Consumer problem using SynchronousQueue. A * call to put() will block until there is a corresponding thread to take() that * element. * * @author Javin Paul */ public class SynchronousQueueDemo{ public static void main(String args[]) { final SynchronousQueue queue = new SynchronousQueue (); Thread producer = new Thread("PRODUCER") { public void run() { String event = "FOUR"; try { queue.put(event); // thread will block here System.out.printf("[%s] published event : %s %n", Thread .currentThread() .getName(), event); } catch (InterruptedException e) { e.printStackTrace(); } } }; producer.start(); // starting publisher thread Thread consumer = new Thread("CONSUMER") { public void run() { try { String event = queue.take(); // thread will block here System.out.printf("[%s] consumed event : %s %n", Thread .currentThread() .getName(), event); } catch (InterruptedException e) { e.printStackTrace(); } } }; consumer.start(); // starting consumer thread } } Output: [CONSUMER] consumed event : FOUR [PRODUCER] published event : FOUR new SynchronousQueue(boolean fair).
What you need to remember about SynchronousQueue in Java.

Here are some important properties of this special type of blocking queue in Java. It is very useful to pass data from one thread to another in a synchronized manner. This queue has no capacity and is blocked until another thread frees it.

  1. SynchronousQueue blocks, and until one thread is ready to take data, another will try to put data.
  2. SynchronousQueue has no volume. That is, it does not contain data.
  3. SynchronousQueue is used to implement a forward queuing strategy, where a thread passes control to a waiting thread, or creates a new one if allowed, otherwise control is not transferred.
  4. This queue does not allow null data. An attempt to add a null element will throw a NullPointerException .
  5. If you use other methods from Collection (such as contains), SynchronousQueue behaves like an empty collection.
  6. You can't use SynchronousQueue's peek method because the element only exists when you try to remove it; Also, you won't be able to insert elements (using any method) until another thread tries to remove it.
  7. You won't be able to use iterator for SynchronousQueue because... it has no elements.
  8. SynchronousQueue can be created with fair rules where access to threads is guaranteed in FIFO order.
Perhaps this is all about SynchronousQueue in Java. We looked at some of the special features of this multi-threaded collection, and learned how to solve the classic producer-consumer problem using SynchronousQueue in Java. By the way, calling it a Queue is not entirely correct, because... it does not contain elements. The call to put() will not complete until another thread calls take(). It is more correct to think of it as a meeting place of threads, where they share an object. In other words, it is a utility for synchronized passing of objects in Java, perhaps a safer alternative to the wait and notify method .
Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION