Summary of Java Multithreading and Concurrent Programming

Java concurrent programming: two ways of interthread collaboration: wait, notify, notify All and Condition

We've talked a lot about synchronization in the past, but in reality, collaboration between threads is needed. For example, the most classic producer-consumer model: when the queue is full, the producer needs to wait for the queue to have space to continue to put goods into it, and during the waiting period, the producer must release the occupancy of critical resources (i.e. queues). Because if the producer does not release the right to occupy the critical resources, then consumers will not be able to consume the goods in the queue, and there will be no space in the queue, so the producer will wait indefinitely. Therefore, in general, when the queue is full, the producer will surrender the occupancy of the critical resources and enter the suspended state. Then wait for the consumer to consume the product, and then the consumer notifies the producer that there is room in the queue. Similarly, when the queue is empty, the consumer has to wait for the producer to inform it that there are goods in the queue. This process of communication is the collaboration between threads.

Today we'll explore the two most common ways of thread collaboration in Java: using Object.wait(), Object.notify(), and using Condition.

The following is an outline of the catalogue of this article:

1. wait(), notify() and notify All ()

Condition

3. Implementation of producer-consumer model

If there is anything wrong, please be more understanding and welcome criticism and correction.

Respect the author's work, please indicate the link of the original text for reprinting.

  http://www.cnblogs.com/dolphin0520/p/3920385.html

1) wait(), notify() and notifyAll() methods are local methods and final methods, which cannot be overridden.

2) Calling the wait() method of an object can block the current thread, and the current thread must have the monitor (lock) of the object.

3) Calling the notify() method of an object can wake up a thread waiting for the monitor of the object. If multiple threads are waiting for the monitor of the object, only one thread can wake up.

4) Calling notifyAll() method can wake up all monitor s waiting for this object;

Implementation of producer-consumer model

public class Test {
    private int queueSize = 10;
    private PriorityQueue<Integer> queue = new PriorityQueue<Integer>(queueSize);
      
    public static void main(String[] args)  {
        Test test = new Test();
        Producer producer = test.new Producer();
        Consumer consumer = test.new Consumer();
          
        producer.start();
        consumer.start();
    }
      
    class Consumer extends Thread{
          
        @Override
        public void run() {
            consume();
        }
          
        private void consume() {
            while(true){
                synchronized (queue) {
                    while(queue.size() == 0){
                        try {
                            System.out.println("Queue empty, waiting for data");
                            queue.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                            queue.notify();
                        }
                    }
                    queue.poll();          //Every time the head element is removed
                    queue.notify();
                    System.out.println("Take an element from the queue, and the queue remains"+queue.size()+"Element");
                }
            }
        }
    }
      
    class Producer extends Thread{
          
        @Override
        public void run() {
            produce();
        }
          
        private void produce() {
            while(true){
                synchronized (queue) {
                    while(queue.size() == queueSize){
                        try {
                            System.out.println("The queue is full, waiting for free space");
                            queue.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                            queue.notify();
                        }
                    }
                    queue.offer(1);        //Insert one element at a time
                    queue.notify();
                    System.out.println("Insert an element into the queue fetch, leaving the queue space:"+(queueSize-queue.size()));
                }
            }
        }
    }
}

Conditions emerged only in java 1.5. It is used to replace traditional Object wait(), notify() to achieve inter-thread collaboration. It is safer and more efficient than using Object wait(), notify(), await(), signal() to achieve inter-thread collaboration in Condition 1. So it's generally recommended to use Condition. As mentioned in the blog post on blocking queues, blocking queues actually use Conditions to simulate inter-thread collaboration.

  • Condition is an interface. The basic methods are await() and signal() methods.
  • Condition relies on the Lock interface, and the basic code for generating a Condition is lock.newCondition().
  • Calling Condition's await() and signal() methods must be protected by lock, that is, between lock.lock() and lock.unlock.

await() in Conditon corresponds to wait() in Object;

signal() in Condition corresponds to notify() of Object.

signalAll() in Condition corresponds to notifyAll() of Object.

Implementation with Condition

public class Test {
    private int queueSize = 10;
    private PriorityQueue<Integer> queue = new PriorityQueue<Integer>(queueSize);
    private Lock lock = new ReentrantLock();
    private Condition notFull = lock.newCondition();
    private Condition notEmpty = lock.newCondition();
     
    public static void main(String[] args)  {
        Test test = new Test();
        Producer producer = test.new Producer();
        Consumer consumer = test.new Consumer();
          
        producer.start();
        consumer.start();
    }
      
    class Consumer extends Thread{
          
        @Override
        public void run() {
            consume();
        }
          
        private void consume() {
            while(true){
                lock.lock();
                try {
                    while(queue.size() == 0){
                        try {
                            System.out.println("Queue empty, waiting for data");
                            notEmpty.await();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    queue.poll();                //Every time the head element is removed
                    notFull.signal();
                    System.out.println("Take an element from the queue, and the queue remains"+queue.size()+"Element");
                } finally{
                    lock.unlock();
                }
            }
        }
    }
      
    class Producer extends Thread{
          
        @Override
        public void run() {
            produce();
        }
          
        private void produce() {
            while(true){
                lock.lock();
                try {
                    while(queue.size() == queueSize){
                        try {
                            System.out.println("The queue is full, waiting for free space");
                            notFull.await();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    queue.offer(1);        //Insert one element at a time
                    notEmpty.signal();
                    System.out.println("Insert an element into the queue fetch, leaving the queue space:"+(queueSize-queue.size()));
                } finally{
                    lock.unlock();
                }
            }
        }
    }
}




Keywords: Java Programming

Added by Blu_Smurf on Fri, 17 May 2019 12:02:16 +0300