假设有两个线程,一个是消费者,一个是生产者,同时去操作同一种商品,其中生产者线程负责生产商品,消费者线程负责消耗商品,需要生产者生产一件商品,消费者消费一件商品。
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();
}
}
从上述图片可以看出,两个线程在消费和生产中出现了问题,消费者在生产的时候还没有生产,消费者就开始消费,这显然是不正常的。。
那么如何解决??
想要解决上述问题,就需要控制多个线程按照一定的顺序轮流执行,此时就需要让线程间进行通信,保证线程任务的协调进行。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();
}
}
在生产者和消费者线程的两个执行任务中同时使用synchronized关键字同步商品消费生产和消费,之后每生产出商品,便调用wait()方法将当前线程处于等待状态,等待消费者线程进行消费,当消费者线程执行任务发现没有商品时便调用notify()方法唤醒对应同步锁上等待的生产者线程,让生产者继续生产,从而继续达到供需有序,均衡。。