假设有两个线程,一个是消费者,一个是生产者,同时去操作同一种商品,其中生产者线程负责生产商品,消费者线程负责消耗商品,需要生产者生产一件商品,消费者消费一件商品。

import java.util.ArrayList;

public class test {
    public static void main(String[] args) {
        ArrayList<Object> goods = new ArrayList<>();
        long start=System.currentTimeMillis();
        //创建一个生产者线程,用于生产商品并将商品存入集合
        Thread thread1 = new Thread(()->{
            int num=0;
            while(System.currentTimeMillis()-start<=100){
                goods.add("商品"+ ++num);
                System.out.println("生产商品"+num);
            }
        },"生产者");
        Thread thread2 = new Thread(()->{
            int num=0;
            while(System.currentTimeMillis()-start<=100){
                goods.remove("商品"+ ++num);
                System.out.println("消费商品"+num);
            }
        },"消费者");

        thread1.start();
        thread2.start();
    }

}

alt

从上述图片可以看出,两个线程在消费和生产中出现了问题,消费者在生产的时候还没有生产,消费者就开始消费,这显然是不正常的。。

那么如何解决??

想要解决上述问题,就需要控制多个线程按照一定的顺序轮流执行,此时就需要让线程间进行通信,保证线程任务的协调进行。Java中在Object类中提供了wait(),notify(),notifyAll()等方法用于解决线程间的通信问题。由于Java中所有类都是Object类的子类或者间接子类,因此任何类的实例对象都可以直接使用这些方法。。

方法申明 功能描述
void wait() 使当前线程放弃同步锁并进入等待,直到其他线程进入此同步锁,并调用notify()或notifyAll()方法唤醒该线程为止
void notify() 唤醒此同步锁上等待的第一个调用wait()方法的线程
void notifyAll() 唤醒此同步锁上调用wait()方法的所有线程

对于上述的例子进行修改,代码如下:

import java.util.ArrayList;

public class test {
    public static void main(String[] args) {
        ArrayList<Object> goods = new ArrayList<>();
        long start=System.currentTimeMillis();

        //创建一个生产者线程,用于生产商品并将商品存入集合
        Thread thread1 = new Thread(()->{

            int num=0;
            while(System.currentTimeMillis()-start<=100){
                synchronized (goods){
                    if(goods.size()>0){
                        try {
                            goods.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }else {
                        goods.add("商品"+ ++num);
                        System.out.println("生产商品"+num);
                    }
                }

            }
        },"生产者");

        Thread thread2 = new Thread(()->{
            int num=0;
            while(System.currentTimeMillis()-start<=100){
                synchronized (goods){
                    if(goods.size()<=0){
                        goods.notify();
                    }else {
                        goods.remove("商品"+ ++num);
                        System.out.println("消费商品"+num);
                    }
                }

            }
        },"消费者");

        thread1.start();
        thread2.start();
    }
}

alt

在生产者和消费者线程的两个执行任务中同时使用synchronized关键字同步商品消费生产和消费,之后每生产出商品,便调用wait()方法将当前线程处于等待状态,等待消费者线程进行消费,当消费者线程执行任务发现没有商品时便调用notify()方法唤醒对应同步锁上等待的生产者线程,让生产者继续生产,从而继续达到供需有序,均衡。。