Home Java javaTutorial Two ways to cooperate between threads in java concurrency: wait, notify, notifyAll and Condition

Two ways to cooperate between threads in java concurrency: wait, notify, notifyAll and Condition

Mar 18, 2017 am 10:09 AM

Cooperation between threads. For example, the most classic producer-consumer model: when the queue is full, the producer needs to wait for the queue to have space before he can continue to put goods into it. During the waiting period, the producer must release critical resources (i.e. the queue) right of occupancy. Because if the producer does not release the right to occupy critical resources, then the consumer will not be able to consume the goods in the queue, and there will be no space in the queue, and the producer will wait indefinitely. Therefore, under normal circumstances, when the queue is full, the producer will be asked to hand over the right to occupy critical resources and enter a suspended state. Then wait for the consumer to consume the goods, and then the consumer notifies the producer that there is space in the queue. Similarly, when the queue is empty, the consumer must wait for the producer to notify it that there is an item in the queue. This process of mutual communication is the cooperation between threads.

wait(), notify() and notifyAll()

[code]/**
 * Wakes up a single thread that is waiting on this object's
 * monitor. If any threads are waiting on this object, one of them
 * is chosen to be awakened. The choice is arbitrary and occurs at
 * the discretion of the implementation. A thread waits on an object's
 * monitor by calling one of the wait methods
 */
public final native void notify();

/**
 * Wakes up all threads that are waiting on this object's monitor. A
 * thread waits on an object's monitor by calling one of the
 * wait methods.
 */
public final native void notifyAll();

/**
 * Causes the current thread to wait until either another thread invokes the
 * {@link java.lang.Object#notify()} method or the
 * {@link java.lang.Object#notifyAll()} method for this object, or a
 * specified amount of time has elapsed.
 * <p>
 * The current thread must own this object&#39;s monitor.
 */
public final native void wait(long timeout) throws InterruptedException;
Copy after login

1) wait(), notify() and notifyAll() methods It is a local method, and it is a final method and cannot be overridden.
 2) Calling the wait() method of an object can block the current thread, and the current thread must own the monitor (i.e. lock) of this object
 3) Calling the notify() method of an object can wake up an object The thread that is waiting for the monitor of this object. If there are multiple threads waiting for the monitor of this object, only one of them can be awakened;
4) Calling the notifyAll() method can wake up all the monitors that are waiting for this object. Thread;
Some friends may have questions: why these three are not methods declared in the Thread class, but methods declared in the Object class (of course, since the Thread class inherits the Object class, Thread can also call the three method)? In fact, this problem is very simple. Since each object has a monitor (i.e. lock), if the current thread is waiting for the lock of an object, of course it should be operated through this object. Instead of using the current thread to operate, because the current thread may be waiting for locks from multiple threads, it would be very complicated to operate through threads.
As mentioned above, if the wait() method of an object is called, the current thread must own the monitor (i.e. lock) of this object, so the wait() method must be called in a synchronized block or synchronized method (synchronized block or synchronized method).
Calling the wait() method of an object is equivalent to asking the current thread to hand over the monitor of this object, and then enter the waiting state, waiting for the subsequent acquisition of the lock of this object again (the sleep method in the Thread class causes the current thread to suspend execution for a period of time, thereby giving other threads a chance to continue executing, but it does not release the object lock);
The notify() method can wake up a thread that is waiting for the monitor of the object. When multiple threads are waiting for the object If the monitor is used, only one of the threads can be awakened, and the specific thread to be awakened is unknown.
Similarly, when calling the notify() method of an object, the current thread must also own the monitor of this object, so calling the notify() method must be done in a synchronized block or synchronized method (synchronized block or synchronized method).
The nofityAll() method can wake up all threads waiting for the monitor of the object, which is different from the notify() method.
One thing to note here: the notify() and notifyAll() methods only wake up the thread waiting for the monitor of the object, and do not determine which thread can obtain the monitor.
Give a simple example: Suppose there are three threads Thread1, Thread2 and Thread3 all waiting for the monitor of object objectA. At this time, Thread4 owns the monitor of object objectA. After the objectA.notify() method is called in Thread4, Thread1, Only one of Thread2 and Thread3 can be awakened. Note that being awakened does not mean that the monitor of objectA is obtained immediately. If the objectA.notifyAll() method is called in Thread4, the three threads Thread1, Thread2 and Thread3 will be awakened. Which thread can obtain the monitor of objectA next depends on the scheduling of the operating system.
Pay special attention to the above. Being awakened by a thread does not mean that it immediately obtains the monitor of the object. Only after calling notify() or notifyAll() and exiting the synchronized block and releasing the object lock can other threads obtain the lock for execution. .

[code]public class Test {
    public static Object object = new Object();
    public static void main(String[] args) {
        Thread1 thread1 = new Thread1();
        Thread2 thread2 = new Thread2();

        thread1.start();

        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        thread2.start();
    }

    static class Thread1 extends Thread{
        @Override
        public void run() {
            synchronized (object) {
                try {
                    object.wait();
                } catch (InterruptedException e) {
                }
                System.out.println("线程"+Thread.currentThread().getName()+"获取到了锁");
            }
        }
    }

    static class Thread2 extends Thread{
        @Override
        public void run() {
            synchronized (object) {
                object.notify();
                System.out.println("线程"+Thread.currentThread().getName()+"调用了object.notify()");
            }
            System.out.println("线程"+Thread.currentThread().getName()+"释放了锁");
        }
    }
}
Copy after login

Condition

Condition only appeared in java 1.5. It is used to replace the traditional Object's wait() and notify( ) to achieve collaboration between threads. Compared with using Object's wait() and notify(), it is safer and more efficient to use Condition1's await() and signal() to achieve collaboration between threads. Therefore, it is generally recommended to use Condition
Condition is an interface, and the basic methods are await() and signal() methods;
Condition depends on the Lock interface, and the basic code to generate a Condition is lock.newCondition()
Calling Condition's await() and signal() methods must be within lock protection, that is to say, they must be used between lock.lock() and lock.unlock

Conditon中的await()对应Object的wait();
  Condition中的signal()对应Object的notify();
  Condition中的signalAll()对应Object的notifyAll()。
Copy after login
[code]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.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                            queue.notify();
                        }
                    }
                    queue.poll();          //每次移走队首元素
                    queue.notify();
                    System.out.println("从队列取走一个元素,队列剩余"+queue.size()+"个元素");
                }
            }
        }
    }

    class Producer extends Thread{

        @Override
        public void run() {
            produce();
        }

        private void produce() {
            while(true){
                synchronized (queue) {
                    while(queue.size() == queueSize){
                        try {
                            System.out.println("队列满,等待有空余空间");
                            queue.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                            queue.notify();
                        }
                    }
                    queue.offer(1);        //每次插入一个元素
                    queue.notify();
                    System.out.println("向队列取中插入一个元素,队列剩余空间:"+(queueSize-queue.size()));
                }
            }
        }
    }
}
Copy after login
[code]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("队列空,等待数据");
                            notEmpty.await();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    queue.poll();                //每次移走队首元素
                    notFull.signal();
                    System.out.println("从队列取走一个元素,队列剩余"+queue.size()+"个元素");
                } 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("队列满,等待有空余空间");
                            notFull.await();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    queue.offer(1);        //每次插入一个元素
                    notEmpty.signal();
                    System.out.println("向队列取中插入一个元素,队列剩余空间:"+(queueSize-queue.size()));
                } finally{
                    lock.unlock();
                }
            }
        }
    }
}
Copy after login

以上就是java-并发-线程间协作的两种方式:wait、notify、notifyAll和Condition的内容,更多相关内容请关注PHP中文网(www.php.cn)!

相关文章:

java notify和notifyAll的对比详细介绍

wait, notify 和 notifyAll的正确用法

通过实例讨论notify()和notifyAll()的本质区别

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

Perfect Number in Java Perfect Number in Java Aug 30, 2024 pm 04:28 PM

Guide to Perfect Number in Java. Here we discuss the Definition, How to check Perfect number in Java?, examples with code implementation.

Weka in Java Weka in Java Aug 30, 2024 pm 04:28 PM

Guide to Weka in Java. Here we discuss the Introduction, how to use weka java, the type of platform, and advantages with examples.

Smith Number in Java Smith Number in Java Aug 30, 2024 pm 04:28 PM

Guide to Smith Number in Java. Here we discuss the Definition, How to check smith number in Java? example with code implementation.

Java Spring Interview Questions Java Spring Interview Questions Aug 30, 2024 pm 04:29 PM

In this article, we have kept the most asked Java Spring Interview Questions with their detailed answers. So that you can crack the interview.

Break or return from Java 8 stream forEach? Break or return from Java 8 stream forEach? Feb 07, 2025 pm 12:09 PM

Java 8 introduces the Stream API, providing a powerful and expressive way to process data collections. However, a common question when using Stream is: How to break or return from a forEach operation? Traditional loops allow for early interruption or return, but Stream's forEach method does not directly support this method. This article will explain the reasons and explore alternative methods for implementing premature termination in Stream processing systems. Further reading: Java Stream API improvements Understand Stream forEach The forEach method is a terminal operation that performs one operation on each element in the Stream. Its design intention is

TimeStamp to Date in Java TimeStamp to Date in Java Aug 30, 2024 pm 04:28 PM

Guide to TimeStamp to Date in Java. Here we also discuss the introduction and how to convert timestamp to date in java along with examples.

Java Program to Find the Volume of Capsule Java Program to Find the Volume of Capsule Feb 07, 2025 am 11:37 AM

Capsules are three-dimensional geometric figures, composed of a cylinder and a hemisphere at both ends. The volume of the capsule can be calculated by adding the volume of the cylinder and the volume of the hemisphere at both ends. This tutorial will discuss how to calculate the volume of a given capsule in Java using different methods. Capsule volume formula The formula for capsule volume is as follows: Capsule volume = Cylindrical volume Volume Two hemisphere volume in, r: The radius of the hemisphere. h: The height of the cylinder (excluding the hemisphere). Example 1 enter Radius = 5 units Height = 10 units Output Volume = 1570.8 cubic units explain Calculate volume using formula: Volume = π × r2 × h (4

Create the Future: Java Programming for Absolute Beginners Create the Future: Java Programming for Absolute Beginners Oct 13, 2024 pm 01:32 PM

Java is a popular programming language that can be learned by both beginners and experienced developers. This tutorial starts with basic concepts and progresses through advanced topics. After installing the Java Development Kit, you can practice programming by creating a simple "Hello, World!" program. After you understand the code, use the command prompt to compile and run the program, and "Hello, World!" will be output on the console. Learning Java starts your programming journey, and as your mastery deepens, you can create more complex applications.

See all articles