Home  >  Article  >  Java  >  What are the ways for Java threads to cooperate?

What are the ways for Java threads to cooperate?

王林
王林forward
2023-05-17 20:34:151380browse

Why do threads need to cooperate?

Threads cooperate with each other to complete a certain work. For example: one thread modifies the value of an object, and another thread senses the change and then performs the corresponding operation. , the entire process starts in one thread, and the final execution is in another thread. Through this model, producers and consumers are separated, thereby achieving the isolation of "What" and "How". The simple way is to let the consumer thread continuously loop to check whether the variables meet expectations, set unsatisfied conditions in the while loop, and exit the while loop if the conditions are met, thereby completing the consumer's work. There are two problems with this kind of collaboration between threads:

(1) It is difficult to ensure timeliness.

(2) It is difficult to reduce overhead. If the sleep time is reduced, such as sleeping for 1 millisecond, consumers can detect changes in conditions more quickly, but it may consume more processor resources, causing unnecessary waste.

Introduction

The two most common ways of thread collaboration in Java: using Object.wait(), Object.notify() and using Condition

Method 1

The wait, notify, and notifyAll methods in Object are defined as follows

  • public final native void notify(); public final native void notifyAll(); public final native void wait(long timeout) throws InterruptedException;

  • ##wait(), notify() and notifyAll() methods are local methods and final methods and cannot be overridden

  • Call the wait() method of an object to block the current thread, and the current thread must own the monitor (i.e. lock) of this object

  • Call the notify of an object The () method can wake up a 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 the threads can be awakened

  • Call notifyAll( ) method can wake up all threads that are waiting for the monitor of this object

  • The reason why these three methods are declared in the Object class is because each object owns a monitor (i.e. lock)

  • To call the wait() method of an object, the current thread must own the monitor (i.e. lock) of this object, so calling the wait() method must be done in a synchronized block or synchronized method

Example

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()+"释放了锁");
        }
    }
}

Running results

Thread Thread-1 called object.notify()

Thread Thread-1 released the lock
Thread Thread-0 acquired the lock

Method 2

  • Condition only appeared in java 1.5, it is used to replace the traditional Object The wait() and notify() of Condition1 realize cooperation between threads. Compared with using wait() and notify() of Object, it is safer and more efficient to use await() and signal() of Condition1 to realize cooperation between threads.

  • Condition is an interface, the basic methods are await() and signal() methods

  • Condition relies on the Lock interface to generate the basic code of a Condition It's lock.newCondition()

  • Calling Condition's await() and signal() methods must be within lock protection, that is to say, they must be between lock.lock() and lock. It can only be used between unlocks

Example

public class Test {
    private int queueSize = 10;
    private PriorityQueue queue = new PriorityQueue(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();
                }
            }
        }
    }
}

The above is the detailed content of What are the ways for Java threads to cooperate?. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:yisu.com. If there is any infringement, please contact admin@php.cn delete