Home > Java > javaTutorial > body text

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

黄舟
Release: 2017-03-18 10:09:08
Original
1222 people have browsed it

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中文网(m.sbmmt.com)!

相关文章:

java notify和notifyAll的对比详细介绍

wait, notify 和 notifyAll的正确用法

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

source:php.cn
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
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!