1、通过共享对象通信(产品)
2、忙等待
1.线程间通信的共享对象(Product)
Product类是生产者与消费者的共享类,是实现他们之间数据的共享对象。生产者生产Product,消费者消费Product,所以在Product类中,分别有一个make和一个sale方法。注意,在这两个方法中,都使用了synchronized关键字,实现线程安全机制。在每个方法中,还用到了wait和notify方法, Obj.wait(),与Obj.notify()必须要与synchronized(Obj)一起使用,也就是wait,与notify是针对已经获取了Obj锁进行操作,从语法角度来说就是Obj.wait(),Obj.notify必须在synchronized(Obj){...}语句块内。从功能上来说wait就是说线程在获取对象锁后,主动释放对象锁,同时本线程休眠。直到有其它线程调用对象的notify()唤醒该线程,才能继续获取对象锁,并继续执行。相应的notify()就是对对象锁的唤醒操作。但有一点需要注意的是notify()调用后,并不是马上就释放对象锁的,而是在相应的synchronized(){}语句块执行结束,自动释放锁后,JVM会在wait()对象锁的线程中随机选取一线程,赋予其对象锁,唤醒线程,继续执行。
具体代码如下:
<span style="font-size:18px;">import java.util.ArrayList;
import java.util.List;
public class Product {
private String name;
private int count;
public static List<Product> list = new ArrayList<Product>();
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getCount() {
return list.size();
}
public void setCount(int count) {
this.count = count;
}
public static List<Product> getList() {
return list;
}
public static void setList(List<Product> list) {
Product.list = list;
}
// /生产方法
public synchronized void make(Product p) {
if (getCount() > 9) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
this.notifyAll();
list.add(p);
}
}
// /消费
public synchronized void sale() {
if (getCount() < 1) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
this.notifyAll();
list.remove(0);
}
}
}
</span>
2.生产者类,生产者类实现了Runnable接口,所以是一个线程类。源码如下:
<span style="font-size:18px;">public class Maker implements Runnable {
Product product = new Product();
public Maker(Product product) {
this.product = product;
}
public void run() {
while (true) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
Product p = new Product();
p.setName("aaa");
product.make(p);
System.out.println("生产:当前剩余产品-->" + product.getCount());
}
}
}
</span>
3.消费者类,消费者类也实现了Runnable接口。
<span style="font-size:18px;">public class Saler implements Runnable {
Product product = new Product();
public Saler(Product product) {
this.product = product;
}
public void run() {
while (true) {
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
product.sale();
System.out.println("消费:当前剩余产品-->" + product.getCount());
}
}
}
</span>
<span style="font-size:18px;">public class Test {
public static void main(String[] args) {
Product product = new Product();
Maker maker = new Maker(product);
Saler saler = new Saler(product);
Thread m1 = new Thread(maker);
Thread m2 = new Thread(maker);
Thread m3 = new Thread(maker);
Thread m4 = new Thread(maker);
Thread s1 = new Thread(saler);
Thread s2 = new Thread(saler);
m1.start();
m2.start();
m3.start();
m4.start();
s1.start();
s2.start();
}
}
</span>
5.运行结果如果下,运行结果中我们可以看到,生产者生产商品的数量,不会超过10个,当商品数量超过10个的时候,生产者就会停止生产,而是等待消费者消费了一定量的商品,才会继续生产。同样,当剩余商品的数量小于0时,消费者也不会继续消费。这就实现了生产者与消费者间的线程通信,两者共享一个数据对象。